What is JavaScript “this”?

Image taken from Unsplash https://unsplash.com/photos/vpOeXr5wmR4

this is a JavaScript keyword which is vastly misunderstood by a lot of developers and this post aims to bridge that gap. While this article is written for beginners but even experienced developers can use it as a refresher. this is a special identifier keyword which is automatically defined in the scope of every function but what it actually refers to is the real deal. This post is divided into three parts and in the first part, we will talk about what thisis and then we’ll talk about some common misconceptions about thisand finally, we will see some features of JS related to this keyword.

Prerequisite

I believe learning is like working out and if you don’t warm yourself up properly then you might end up hurting yourself. Thus before talking about this, let’s talk about a few JavaScript concepts which you should be familiar with for this article.

1) The variables declared in the global scope as var a = 2; are nothing but global-object properties of the same name. Yes, they are not copies of each other but are each other. To make this clearer look at the example below how we are able to access the value of x as the key of the global object window . Further, a thing to must note here is this only works with declarations using var, not let/const .

<a href=“global-object-key.js · GitHub”>global-object-key.js · GitHub</a>

2) Call-site: The location where a function is called from is called call-site. Usually finding the call-site just comprises of locating the line where the function is called from but this can be misleading as a function can be called at multiple places in the code. Thus the most accurate way to find the call-site is to find the call-stack and then see where the function was called from or in other words what was the previous function in call-stack. Let’s understand this with an example.

<a href=“call-site.js · GitHub”>call-site.js · GitHub</a>

What is this?

this is a binding made for each function invocation whose value depends on how and where the function is called. Binding made for this is usually related to variables declared using var and JavaScript running in non-strict mode. Further on the basis of the call-site, we can divide such bindings into four parts as given below:

  • Default Binding
  • Implicit Binding
  • Explicit Binding
  • new Binding

Default Binding: When we call a function in the global scope normally with no special decoration. this inside the function gets bound with the global scope. Yes, you can access all global variables using this inside such functions. One thing to notice here is it is only applicable for non-strict mode and variables defined using var .

<a href=“default-binding.js · GitHub”>default-binding.js · GitHub</a>

Strict mode: The value of this is undefined in this case.

let/const: The variables defined with let/const are not bound.

Implicit Binding: When the call-site of function has a containing object (context object) as given below. That context object is bound to this inside that function. In the example below, obj is the context object and this gets bound to this object and all the keys will be accessible inside the function using this.

<a href=“implicit-binding.js · GitHub”>implicit-binding.js · GitHub</a>

Strict mode: This will work the same as non-strict mode.

let/const: Not applicable

Explicit Binding: This binding gives us the superpower to assign this to anything. We can achieve this using call(…) and apply(…) methods. Yes, we can set thisto an object, variable, function or anything. But there’s a catch, null and undefined are replaced with global object and primitives are converted into equivalent objects. Whatever we will pass as the first argument that will be used as this binding by the function call, sweet.

<a href=“explicit-binding.js · GitHub”>explicit-binding.js · GitHub</a>

Strict mode: null and undefined don’t get replaced with the global object and primitives are not converted into objects.

let/const: Not supported when this binds to the global object (either directly or after getting replaced from null or undefined ) but variables defined with let/const can be directly passed as this and it will get bound.

New Binding: This one can feel a little odd from the rest of the binding rules. In this kind of binding, if we invoke the function with new keyword and assign it to a variable then this is bound to that variable. Look at the example below for understanding. Here we assign the value of new doSomething() to bar thus inside the function, this gets bound to bar.

<a href=“new-binding.js · GitHub”>new-binding.js · GitHub</a>

Strict mode: No effect

let/const: The variables defined can be both let/const, the same behaviour is observed.

What this isn’t?

Let’s see the most common misconceptions about this which a lot of developers have and dive deeper into each of them. People think this in a function refers to:

  1. Itself
  2. Its Scope

Itself Many developers believe that this refers to the function itself in which it is called which is wrong. Below is a simple example to prove it.

<a href=“itself.js · GitHub”>itself.js · GitHub</a>

Rather the correct way to keep track of how many times increase is called would be to actually use the call method to explicitly define the this keyword to be the increase object (itself). The below-given code example is a working example of it.

<a href=“counter.js · GitHub”>counter.js · GitHub</a>

Its Scope Another famous misconception developers have is that they think that it refers to the function’s scope. It is a tricky one because in global scope, this refers to the global scope itself but it is quite a misguided statement as we saw that it is not true in the previous section.

More JavaScript Features around this

bind() function: ES5 introduced this function which helps bind the value of this explicitly. bind returns a function with this set to the first argument of bind. This is something similar to call and apply but the difference is once we use bind the function retains its context so that it can be reused.

<a href=“bind.js · GitHub”>bind.js · GitHub</a>

arrow function: In these functions, this retains the value of the enclosing lexical context’s this. In global code, it will be set to the global object. Let’s see a few examples below:

<a href=“this.js · GitHub”>this.js · GitHub</a>

this in classes: The behaviour of this in classes and functions is the same since classes are nothings but functions under the hood. Still, I would suggest a read here that has a few corner cases. A common convention is to override this behavior so that this within classes always refers to the class instance. This is commonly seen in React Class components.

this as a DOM handler: When a function is used as an event handler, its this is set to the element on which the listener is placed. The code given below will print the DOM element itself.

<a href=“dom.html · GitHub”>dom.html · GitHub</a>

References and Recommended Reads:

  1. You Don’t Know JS: this and Object Prototype
  2. this: MDN docs

What is JavaScript “this”? was originally published in Walmart Global Tech Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Article Link: What is JavaScript “this”?. this is a JavaScript keyword which is… | by Rahul Gurung | Walmart Global Tech Blog | Feb, 2022 | Medium