The Magic Of this Keyword

JavaScript borrows this keyword from C++, where it is used to point to an instance of an object from within its own class definition. There is absolutely no confusion about this keyword in C++ because this keyword is never used for any other intent than to point to an instance of an object from its constructor!

Here’s a list of my best web development tutorials.

Overview

So let’s summarize for JavaScript:

  1. The this keyword also keeps track of execution context also often referred to by some as the lexical scope or lexical environment. Think of lexical scope as location in memory allocated for all local variables to that scope.
  2. The link to the execution context can change: for example using this inside an arrow function is not the same as using this in ES-style function. Arrow functions are not constructors and cannot be used to instantiate an object. So they don’t even have their own this context. But they do have this keyword. So what does it point to? It is likely to be the parent context just outside of it. It has a “transparent” scope, I guess you can say.
  3. The link to execution context is also established when this is referred by a callback function, even if that function was defined inside an object’s constructor (when function or class is used as an object constructor.)

Where It All Begins

Let’s take a look at the original idea behind this keyword:

function Cat() {
this.name = "felix";
console.log(this); // Cat {name: "felix"}
}
let cat = new Cat(); // Cat {name: "felix"}
class Mouse {
constructor() {
this.name = "mappy";
console.log(this); // Mouse {name: "mappy"}
}
}
let mouse = new Mouse(); // Mouse{name: "mappy"}

The Secondary Purpose Of this Keyword

When used outside of object instances (previous examples) the this keyword takes on a completely new meaning.

function abc() {
console.log(this);
}
abc(); // [object Window] -- points to window object
function abc() {
console.log(this);
}
let type = new abc(); // abc{} -- self
typeof type;
function food(kind) {    this.kind = kind;
this.cook = cook; // functions are hoisted, so it's perfectly
// fine to call or assign function names
// before they are defined.
function cook(sec) {
setTimeout(function() {
console.log(this.kind + " cooked for " + sec + " seconds.");
}, sec * 1000);
}
}
let soup = new food("soup"); // <--- this.kind = "soup"soup.cook(2); // undefined cooked for 2 seconds.
function food(kind) {    this.kind = kind;
this.cook = cook; // functions are hoisted, so it's perfectly
// fine to call or assign function names
// before they are defined.
function cook(sec) { // remember, in cook(), this still points to food object
// and not the window object (like in setTimeout)!
// this means we can still capture it here, and pass it
// into setTimeout callback manually, so let's make a
// reference to this and call it that. (or anything you want)
let that = this; // Now inside setTimeout, refer to that.kind not this.kind:
setTimeout(function() {
console.log(that.kind + " cooked for " + sec + " seconds.");
}, sec * 1000);
}
}
let soup = new food("soup");soup.cook(2); // soup cooked for 2 seconds.

You hear a lot about “this binding” — but what in the world is it?

Well, that’s exactly the idea we’ve just covered above.

Arrow Functions To The Rescue

Before arrow functions, programmers had to bind this to that manually. But arrow functions can automatically fix this problem. Arrow functions have a “transparent” scope. In other words in setTimeout(()=>{this}, 1000) the this keyword does not point to [object Window]. It points to whatever is outside of it. And in the previous case outside is the food object. This fixes the need to constantly have to bind this to the proverbial that.

function food(kind) {
this.kind = kind;
this.cook = cook;
function cook(sec) {
setTimeout(() => {
console.log(this.kind + " cooked for " + sec + " seconds.");
}, sec * 1000);
}
}
let soup = new food("soup");
soup.cook(2); // soup cooked for 2 seconds.

How to reconcile the two “this” use cases, without losing your mind?

Well, this is the fun part.

So when does this *not point to [object Window]?

In the second use case when this points to the instance of an execution context rather than the instance of the object from constructor we’re in… what are the cases when this will not point to [object Window]?

Keep writing code.

These types of concepts take time to sink in.

Issues. Every webdev has them. Published author of CSS Visual Dictionary https://amzn.to/2JMWQP3 few others…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store