The this Keyword in JavaScript Explained with Examples

In this blog post, I’ll try my best to explain how the this keyword in JavaScript works. We’ll be looking at some guidelines when it comes to the use of this keyword in JavaScript. And to make it stick in your brain, we’ll be running some example tests together.

Moreover, because a picture is worth a thousand words, I’ll provide you with a diagram that will sum up all of this by the end of this article.

So, to start let’s have…

A general idea about the this keyword in JavaScript

In one of my posts that explains how JavaScript works behind the scenes, I have mentioned that the this binding happens during the phase of creation of an execution context. In other words, it does occur during runtime.

And talking about execution contexts, I also stated that there’s basically two types of execution contexts in JavaScript: the global execution context, and the functional execution context.

This being said, it helps us to retrieve some general guidelines when it comes to the this binding in JavaScript. These guidelines are going to cover most of the cases. However, there’re some exceptions that we’re going to see afterwards.

Common situations

the this keyword in the global context

During the phase of creation of the global execution context – which happens at the beginning each time your run your JavaScript code – the this object will always refer to the global object. And we mean by the global object the context in which your JavaScript is running. For instance, if you are running your JavaScript code in a browser then the global object will refer to the window object. Let’s demonstrate this…

console.log(this);

If you copy/past this line on your JavaScript console and hit enter to run it, you will get something similar to the following printed out to your console.

You could get something different if you are running your code in Node (which is runtime for JavaScript).

Though, no matter the context in which you are running your JavaScript code, you could easily access the global object – which the this object refer to in the global execution context – by through golbalThis object like in the following way…

console.log(globalThis);

By running this line of code, you’ll get the window object if you are running it in the browser or something else if you’re doing it in Node.

the this keyword in a functional context

The creation of a functional execution context happens each time we invoke a function. Therefore, the this binding, in contrast of the global execution context, will depend on how the function is called in most cases.

So, knowing that generally in a program we can call a function whether directly or via an object will limit the scope for us to be able to distinguish and identify the this object binding.

Direct invocation of a function

When you invoke a function directly in your JavaScript code, the this object will be bound to the global object if the strict mode ain’t used.

In the following example, we’re not using the strict mode, and we are running our code in the browser.

function test1() {
  console.log(this);
}

test1(); // window object

So, invoking the function test1 directly in non strict mode will print out the window object which is the global object in this case.

However, if we run the same code using the strict mode instead,

var test2 = function () {
  "use strict"; // see strict mode
  console.log(this);
};

test2(); // undefined

Then, calling the function test2 directly will output undefined to the console.

Invocation of a function via an object

Now, in certain cases, we can call a function (method) through an object like in the following piece of code,

var obj = {
  a: 123,
  test3: function () {
    console.log(this);
  },
};

obj.test3();

If we run this code, we will get,

In fact, in this example, test3 is a method of the object obj. Therefore, when invoking it, the this object will be bound to the object that the method is called on. As result, the obj itself will be printed out to the console.

To end up this section, as a rule of thumb, generally you would see on the left side of a function invocation in order to immediately identify the value of this. If there’s nothing than it refers to the global object. If it’s called via an object then this will refer to that object. Nevertheless, like everything in this life, there’re some exceptions…

Exceptions

Explicit binding of this

In some cases, the this value can be explicitly set to a function before it gets invoked. This can be done using Function.prototype.bind() method. So, if you do this, no matter how you use the function, this will always refer to the object you have set to that function,

function sayHi() {
  return this.greeting;
}

function printThis() {
  console.log(this);
}

var obj1 = {
  greeting: "Hello folks!",
};

var greetPeople = sayHi.bind(obj1);
var printThis = printThis.bind(obj1);
console.log(greetPeople()); // Hello folks!
printThis(); // obj1

In the example above, we have defined two functions sayHi and printThis, and an object obj1 to be used as a value of this for both functions.

Then, we’re binding obj1 to both functions before invoking them in the two last lines of the code. Therefore, two bound functions, greetPeople and printThis are created.

So, invoking greetPeople will print the string “Hello folks!” that is being accessed through this.greeting in the body of the function. In this case this refers to obj1 set before its call using the bind method.

In the same way, the value of this is printed to the console by invoking printThis. It’s a sort of a double check that proves we’re talking about the same object obj1 when referring to this.

Arrow functions

The this binding in arrow functions is a special case. In fact, they do not have their own bindings to this. Therefore, this retains the value of the enclosing lexical context’s this when the function was created. What does all of that mean? In other words, it means that no matter who’s the caller of the function and how it’s called, this inherits its value from the parent scope.

Let’s have a look at this example to have a better understanding,

obj2 = {
  scope1This : this,
  test4: () => this, // Avoid doing this !
  test5: function () {
    var scope2This = this;
    console.log(scope2This);
    return () => this === scope2This;
  }
};
console.log(obj2.test4() === obj2.scope1This); // true
var test5 = obj2.test5(); // output obj2 object
console.log(test5()); //true

First of all, notice that you should never use arrow functions as methods like we did in line 3. However, for the sake of testing things out, we broke the rule this time.

If you try this piece of code on your JavaScript console, you will get “true” for lines 10 and 12. Indeed, for line 10, the method test4 inherits the value of this from its parent scope. Thus, its value is same as the value of scope1This that refers to the global object (the window object). And if you want to double check this, you could try,

console.dir(obj2.scope1This); // Window object

Moreover, in line 11, we are assigning the arrow function to the variable test5, then invoking it in line 12. The expression this===scope2This evaluates to true, and that’s obvious. Indeed, the arrow function does inherit its this binding from the parent enclosing context which is in this case the obj2 object. Need a proof? Notice that obj2 is printed out to the console in line 11 and that’s the value of scope2This in line 6.

One more last this concerning arrow functions. The explicit binding has no effect on them.

Let’s see the following example,

var random = () => {
  console.log(this.randomValue);
}

var randomObj = {
  randomValue : Math.random().toFixed(2), // a floating number between 0 and 1
}

var randomFunc = random.bind(randomObj);
randomFunc(); // undefined

The example above seems to be correct. However, if you try it out, you will get undefined in line 10. That proves that explicit binding has no effect on arrow functions. So, be aware when using them!

Now I have a little exercise for you…

Your task is to fix the latter example by making one single change on the code in a way that we get a random number instead of undefined. Could you? I bet you can if you’ve read carefully the section before this one…

Sum up…

We are finally at the end of this blog post. However, before we end up, I would like to share with you the following diagram. It sums up the different possible cases to define the this binding in JavaScript.

Hope after reading this post you’re able to have a good grasp of the this keyword in JavaScript, and how to identify its value with ease. Still, if you have any questions, please, make sure to use the comment section below.

Enjoy 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *