JavaScript’s this: how it works, where it can trip you up

In JavaScript, the special variable this is relatively complicated, because it is available everywhere, not just in object-oriented settings. This blog post explains how this works and where it can cause problems, concluding with best practices.

To understand this, it is best to partition the locations where it can be used into three categories:

In functions:this is an extra, often implicit, parameter.

Outside functions (in the top-level scope):this refers to the global object in browsers and to a module’s exports in Node.js.

In a string passed to eval():eval() either picks up the current value of this or sets it to the global object, depending on whether it is called directly or indirectly.

Let’s examine each of these categories.

this in functions

That’s the most common way of using this, because functions represent all callable constructs in JavaScript, by playing three different roles:

this-related pitfalls

There are three this-related pitfalls that you should be aware of. Note that in each case, strict mode makes things safer, because this is undefined in real functions and you get warnings when things go wrong.

Pitfall: forgetting new

If you invoke a constructor and forget the new operator, you are accidently using it as a real function. Hence, this does not have the correct value. In sloppy mode, this is window and you’ll create global variables:

Pitfall: extracting methods improperly

If you retrieve the value of a method (instead of invoking it), you turn the method into a function. Calling the value results in a function call, not a method call. This kind of extraction can happen when you pass a method as an argument for a function or method call. Real-world examples include setTimeout() and registering event handlers. I’ll use the function callIt() to simulate this use case synchronously:

bind() created a new function that always receives a this whose value is counter.

Pitfall: shadowing this

When you use a real function inside a method, it is easy to forget that the former has its own this (even though it has no need for it). Therefore, you can’t refer from the former to the method’s this, because it is shadowed. Let’s look at an example where things go wrong:

Best practices

Conceptually, I think of real functions as not having their own this and think of the aforementioned fixes as keeping up that illusion. ECMAScript 6 supports this approach via arrow functions – functions without their own this. Inside such functions, you can freely use this, because there is no shadowing: