Getting a handle on JavaScript’s “this”

Evan Schechter
Aug 8 · 4 min read
From Programming with Mosh on YouTube

Any programmer with experience in an object-oriented language like Java has seen the keyword this or the similar Ruby and Python self. In those languages, this and self simply refer to the current instance of the class in which the keyword appears.

Since JavaScript was written to superficially imitate Java’s look and syntax, JavaScript’s developers chose to also employ the this keyword. The catch is that in many situations, JavaScript’s this acts completely differently from the self and this keywords in true object-oriented languages. (For more on the difference between JavaScript and languages with native support for classes, check out my last post). To emphasize this contrast, here’s a more in-depth explanation of this in object-oriented languages.


How It Works in OO Languages

As hinted above, in true object-oriented languages, the value of this in a method is determined by where the method is defined. For example, take a look at this pseudo-code, written to mimic some true object-oriented language:

class Foo:
constructor():
this.example_var = 10
end
say_var():
print this.example_var
end
end

Now when we define instance = new Foo() and call instance.say_var(), this in say_var will look at where the method is defined, in this case, as an instance method of Foo. Based on this context, this will refer to an instance of Foo, and say_var() will successfully print the example_var attribute for the instance, which we defined to be 10. In pure object-oriented languages like Java, this is all that this is: a way to access the current instance of a class. Furthermore, the value of this is determined purely by the context of the method where this appears.


The Situation in JavaScript

I’m not gonna lie; it’s a little more complicated. The MDN, our JavaScript bible, has this to say:

In most cases, the value of this is determined by how a function is called (runtime binding). It can’t be set by assignment during execution, and it may be different each time the function is called.

At an overly simplistic level, this means that, in most circumstances, this in a function f()will refer to whatever appears to the left of the dot when f() is invoked. In myObject.f(), this will refer to myObject. Alternatively, when f() is not invoked on any object, this will default to the global context, which is typically the Window object (more on this later). Anyway, here’s an example of the value of this depending on where the function containing it is invoked rather than where it is defined:

const obj = {
attr: "whaddup",
objMethod: function(){
console.log(this.attr)
}
}

Then:

obj.objMethod()
>>> "whaddup"

Make sense? It seems like this here is behaving very similar to this in true OO languages, referring to the object where a method is defined. However, this behavior is more of a coincidence than a feature of JavaScript. In this case, the context in which this is defined, obj, coincides with the object on which it is called (also obj). But this is not necessarily the case. Observe:

const globalFunc = obj.objMethod
globalFunc()
>>> undefined

Here, this originally appears in objMethod, which is defined on the object obj. But when we make a copy of objMethod and invoke globalFunc, the execution context of globalFunc becomes the global object, which in the case of browser-based JavaScript is the Window. Thus, this when globalFunc is invoked refers to the Window, which has no key attr. This explains why the second example results in undefined being printed to the console.


Binding “this” and Arrow Functions

More often than not, we would much rather the value of this depend on where the method containing it is defined rather than where the method is executed. That’s why this works that way in OO languages. And that’s where .bind() and arrow functions come in. These constructs give us a level of control over this, rather than just having the keyword be bound willy-nilly when methods are called. Here’s an example:

Then doggo.eatSnacksFunction() prints:

>>> is eating cabbage
>>> is eating carrots
>>> is eating bones

So we were able to print out the contents of favSnacks but were not able to access the doggo’s name. Almost the behavior we want, but no cigar. Inside the eatSnacksFunction, the first this successfully refers to the doggo object, allowing us to access favSnacks. This should come as no surprise, as doggo is to the left of the dot in doggo.eatSnacksFunction(). The problem occurs when we enter the callback function inside forEach().

Because this anonymous function is not defined on any object, the this inside of it refers to the Window object, which has no name attribute. So how can we make the inner this refer to doggo? We have two options:

Now, both functions, when called on doggo, will successfully print:

>>> winfield is eating cabbage
>>> winfield is eating carrots
>>> winfield is eating bones

Let’s talk about what happened. In the first function, the .bind(this) means the following: Make this inside the anonymous function refer to the same this as the outer function, firstSuccessfulEatSnacks. Thus, this in the anonymous function is now doggo, giving us the desired behavior. More generally, calling .bind(someObject) on a function will make this inside that function refer to someObject.

OK, cool. But what about the second function? In a way, it’s just syntactic sugar for the first. That fancy => arrow function essentially means: Make an ordinary function, then bind this to the this of the outer function. Just like the first example, only cleaner syntax. Take a second to review this code; this is a complicated topic.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade