JavaScript this Keyword Complete Tutorial

In this section, we will learn what the `this` keyword is and how to use it in JavaScript.

What is this Keyword in JavaScript?

We use the `this` keyword inside the body of functions and methods to refer to the object that invoked the function or the target method.

Let’s say we have a function like this:

function Person(firstName, lastName){
        this.firstName = firstName; 
        this.lastName = lastName;
        this.printInfo = function(){
          console.log(this.firstName, this.lastName);
        }
}

As the body of the `Person` function shows, after the keyword `this` we use dot `.` operator and a property name. Again, the `this` keyword refers to the object that invokes the function. So the property that comes after the `this` keyword is part of the object that invoked the function.

JavaScript Binding this

Linking an object to the `this` keyword is called binding and is not possible to figure out the object just by looking at the body of that function.

To figure out what object the `this` keyword will bind to; we should take a look at the place where the target function is being invoked.

const obj = {
  
}
function Person(firstName, lastName){
  this.firstName = firstName; 
  this.lastName = lastName;
  this.printInfo = function(){
    console.log(this.firstName, this.lastName);
  }
}
obj.prs = Person;
obj.prs("John","Doe");
obj.printInfo();

Output:

John Doe

Here there’s a function named `Person` and an object with the name `obj`.

The object `obj` does not have any property at first.

But then in the statement:

obj.prs = Person;

We’ve added a new property named `prs` and assigned the memory address of the function in which the Person identifier has its address as well.

So now basically the body of the object `obj` is like this:

const obj = {
        prs: function (firstName, lastName){
        this.firstName = firstName; 
        this.lastName = lastName;
        this.printInfo = function(){
          console.log(this.firstName, this.lastName);
        }
      }

Note: there’s no copy of the Person function in the object `obj`. Here we just for the sake of explanation added the body of this function to the object as well. In reality, though, the object has only the `prs` property and that property has the `address` of the target function as its value. This address is the location of the memory space that the `Person` function is stored there.

Now in the statement:

obj.prs("John","Doe");

We invoked the `prs` property of the `obj` object. This means the body of the target function is invoked and the two arguments “John” and “Doe” are assigned to the `firstName` and `lastName` parameters, respectively.

Alright, at the beginning of this section we mentioned that the `this` keyword refers to the object that invokes the target function, right?

So here the object `obj` is invoking the function and so the `this` keyword refers to the `obj` object.

Now when the execution engine executes the body of the target function, it sees the body of the function like this:

function (firstName, lastName){
        obj.firstName = firstName; 
        obj.lastName = lastName;
        obj.printInfo = function(){
          console.log(this.firstName, this.lastName);
}

As you can see, the `this` keyword is bound to the invoking object `obj`.

Also, as explained in the object section, when we invoke a property of an object to assign a value into it, the execution engine will check the object to see if there’s a property with such name or not. If it can’t find the property, it will automatically create one.

So here because the `obj` does not have `firstName`, `lastName` and the `printInfo` properties, it will create them and assign the related values to these properties.

Now in the last statement:

obj.printInfo();

The execution engine will check the `obj` object to see if there’s a property named `printInfo` or not. So because there’s one now, its body will be invoked.

The body of this method is:

function(){
          console.log(this.firstName, this.lastName);
}

Again, here we’ve used the `this` keyword and so the execution engine will look at the object and binds the `this` keyword to that object.

So basically the body of the function after binding, conceptually becomes this:

function(){
          console.log(obj.firstName, obj.lastName);
}

Of course, now the values of these two properties will be invoked and sent to the browser’s console.

Rules of Binding in JavaScript

In total, there are 4 rules that we need to check when invoking a function that has the `this` keyword in it. These 4 rules help us to figure out what object the `this` keyword will bind to.

1- Was the Target Function Called with the `new` Keyword?

Calling a function via the `new` keyword is used to create a new object. When we use the `new` keyword, a new object will appear in the memory (an empty object basically) and all the `this` keywords in the function will bind to that object.

Example: invoking a function via the `new` keyword

In the function constructor section you’ll see how to use the `new` keyword and functions to create such object but for now this is the way we use the `new` keyword:

function Person(firstName, lastName){
        this.firstName = firstName; 
        this.lastName = lastName;
        this.printInfo = function(){
          console.log(this.firstName, this.lastName);
        }
      }
      const obj = new Person("John","Doe");

So in this example, all the properties in the `Person` function will become the properties of this newly created object and the address of the object will be stored in the `obj` identifier.

2- Was the Target Function Called with the `call`, `apply`, or `bind` Function That Specifies an Explicit `this`?

Functions at their core are a sub-type of object. This means a function can have properties and methods. In the prototype section, we will back to this topic, but for now just remember that functions have 2 methods named `call` and `apply`.

When we want to explicitly bind the `this` keyword inside a function to an object, we can use either of these two methods.

Example: invoking a function via call() method

let prs = {

}
function Person(firstName, lastName){
  this.firstName = firstName; 
  this.lastName = lastName;
  this.printInfo = function(){
    console.log(this.firstName, this.lastName);
  }
}
Person.call(prs, "John","Doe");
prs.printInfo();

Output:

John Doe

In the statement:

Person.call(prs, "John","Doe");

We’ve used the `call` method to explicitly bind the `prs` object to the `this` keyword in the body of the function.

So after that, when we called the statement:

prs.printInfo();

The execution engine will not return error because in the body of the `Person` function the engine has created the `printInfo` property for the `prs` object and stored the memory address of the function as the value of the `printInfo` property.

Note: In the call section as well as the apply section, these two methods are explained in greater details.

3- Was the Target Function Called via a Containing/ Owning Object?

This rule basically is telling that see if the target function is invoked via the name of an object. If yes, then the object that invokes the method is considered as the object that will be bound to the `this` keyword inside the body of that function.

Example: invoking a function via owning object in JavaScript

let prs = {
        firstName: "John",
        lastName: "Doe",
        printInfo: function(){
          console.log(this.firstName, this.lastName);
        }
      }
      prs.printInfo();

Here the object `prs` is invoking the `printInfo()` method and so the `this` keyword binds to the `prs` object.

4- Default: Global Object (Except Strict Mode)

If the target function is called by itself, then the `this` keyword is bounded to the global object.

Example: directly invoking a function in JavaScript

var firstName;
var lastName;
function Person(firstName, lastName){
  this.firstName = firstName; 
  this.lastName = lastName;
  this.printInfo = function(){
    console.log(this.firstName, this.lastName);
  }
}
Person("Omid","Dehghan");
console.log(firstName, lastName);

Output:

Omid Dehghan

Here, the two variables `firstName` and the `lastName` are considered as the variables of the global object.

So according to the fourth rules, if the target function is invoked by itself (just like the invocation of the `Person` function in this example) then the `this` keyword in that function will bind to the global object.

So here the `firstName` and the `lastName` variables will get the values `Omid` and `Dehghan` respectively.

That’s how the last statement `console.log (firstName, lastName);` sent the value `Omid Dehghan` to the browser’s console.

JavaScript Arrow Function and this keyword

You should know that the rules mentioned above, does not work for arrow functions!

In fact, there’s no binding in arrow functions at all! Or in a simple word, arrow functions don’t know anything about the `this` keyword in the first place!

Note: inside an arrow function, the `this` keyword is like an identifier (like a variable name) that there’s no information about it in the arrow function. So the execution engine will check the enclosing scopes to see which one of them knows anything (any value) for this keyword.

When we put the `this` keyword in an arrow function, it will check its parent scope to see if that scope knows something about the `this` keyword! If yes, it will try to resolve the `this`, otherwise the parent of the parent scope will be checked until we reach to the global scope.

Basically, for an arrow function, lexical scopes are checked for the `this` keyword and if none of them can’t bind the `this` keyword to an object (perhaps because they are arrow function as well) then the `this` keyword will bind to the global object.

Example: using this in JavaScript Arrow Function

const emp = {
  name: "John", 
  lastName: "Doe", 
  printName: ()=>{
    console.log(this.name + " "+ this.lastName);
  }
}
var name = "Omid"; 
var lastName = "Dehghan ";
var printName = emp.printName; 
emp.printName();
printName();

Output:

Omid Dehghan

Omid Dehghan

Here we’ve called the `printName` function using both `emp` object and passing a reference of it to a variable of the global object and calling it from there.

In both cases, the result turned to be `Omid Dehghan`.

Let’s see what happened here:

In the statement:

emp.printName();

The execution engine sees the `printName()` function as an arrow function and so it will try to resolve the `this` keyword in its parent scope (lexically). So here it checks to see who’s the parent scope of this arrow function and it sees that the global scope is the only parent left in the chain of scopes (because the arrow function is not in the boundary of another function). And in the global scope, the `this` keyword is always bound to the global object.

So because the global object has two variables `name` and `lastName`, the value of these two variables will be used in the target arrow function at the end.

For the second time we’ve called the `printName()` function, the same process occurs and this time also the global object binds to the `this` keyword and we get the same result here as well.

Example: JavaScript this keyword and the arrow function

const emp = {
  name: "John", 
  lastName: "Doe", 
  printName: function () {
    var printName = ()=>{
      console.log(this.name + " "+ this.lastName);
    }
    printName();
  }
}
var name = "Omid"; 
var lastName = "Dehghan ";
var printName = emp.printName; 
emp.printName();
printName();

Output:

John Doe

Omid Dehghan

This time, the arrow function is inside the body of a function expression!

So let’s see what happened:

When the `emp.printName()` statement was executed, inside the body of this method, we have an arrow function that calls `this.name` and `this.lastName`. As mentioned before, an arrow function doesn’t know anything about the `this` keyword and so it will try to resolve this keyword in the parent scope. So here it will check the function expression (which is the parent of this arrow function) to see what the `this` keyword is binding to.

In the function expression because the `emp` invoked the `printName()` function, then the `emp` object binds to the `this` keyword. So then the arrow function uses the `emp` object as the replacement of the `this` keyword.

That’s how the first call to the `printName()` function resolved.

Now the second time we’ve called the `printName()` function alone, the `this` keywords bind to the global object. And for this reason, the arrow function this time replaced the `this` keyword with the global object and that’s how we got the values of the `name` and `lastName` of the global object.

Facebook
Twitter
Pinterest
LinkedIn

Top Technologies