Understanding the JavaScript "this" keyword

·

4 min read

Introduction

There is no doubt that figuring out the value of "this" keyword in a function can be confusing most of the time. however, it becomes easier to understand when you take note of these five important rules.

  1. Implicit Binding

const car = {
  name: "Lexus",
  brand: "Toyota",
  model: "2007",
  carBrandAndModel() {
    console.log(`the brand of the car is ${this.brand} and the model is ${this.model}`)
  }
}
car.carBrandAndModel();

Consider an object named car with the following properties and method as shown in the code above. to call or invoke this function, we use the dot notation on the car object followed by the method which in this example is carBrandAndModel. Following the implicit binding rule, when a function is called or invoked using the dot notation, the object to the left of the dot is what the "this" keyword references, in our scenario, the "this" keyword references the car object. this means that "this.brand" is the same as car.brand which in our example is Toyata. Therefore, the output of this method would be: "the brand of the car is Toyota, and the model is 2007".

  1. Explicit Binding

const car = {
  name: "Lexus",
}

function carName() {
  console.log(`the name of the car is ${this.name}`)
}

carName.bind(car)
carName.call(car)
carName.apply(car)

Let us consider a car object and a sperate function carName that logs this.name to the console. to invoke the carName function in the context of the car object, we need to explicitly specify the context using one of the three methods ".bind, .call, .apply" as shown above in the code sample. these are built-in method available in every function. in this example, the "this" keyword references the object passed in as the parameter. so this.name references to car.name which in our case is "Lexus". Therefore, the output would be "the name of the car is Lexus".

  1. New Binding

function car(name) {
    //this ={}
    this.name = name
}

const car1 = new car("Lexus")
const car2 = new car("corolla")

Consider a constructor function named car that accepts name as a parameter. within this function, we assign the this.name to the name parameter. This pattern allows to create multiple instances of car object, each with different name.

when a function is invoked with the new keyword, JavaScript internally create a new empty object as commented in the code above that the "this" key word reference to. so, rule three, this keyword within a function invoked with the new keyword always references a newly created empty object.

  1. Default Binding

function carName() {
  console.log(`the name of the car is ${this.name}`)
}

This rule acts as a fallback when none of the other three rules apply. let us consider the carName function. when calling the carName function in a standard manner without the .bind, .call, .apply as mentioned in rule.2 and without the "new" keyword, the output would be "the name of the car is undefined". why? the reason is that when other rules don't fit, JavaScript uses default binding, this means that the "this" keyword refer to the global this object. if there is no name in the global scope, this.name is undefined. if there was a global name, it would use that.

  1. Lexical Binding

const car = {
  name: "Lexus",
  brand: "Toyota",
  model: "2007",
  carBrandDetails() {
    const details = function() {
        console.log(`the brand of the car is ${this.brand}, name is {this.name}`)
    }
  }
}
car.carBrandDetails();

//modified function
const car = {
  name: "Lexus",
  brand: "Toyota",
  model: "2007",
  carBrandDetails() {
    const details = () => {
        console.log(`the brand of the car is ${this.brand}, name is ${this.name}`)
    }
  }
}
car.carBrandDetails();

Consider a car object with a carBrandDetails method which contains a nested details function. when invoking car.carBrandDetails, the output is "the brand of the car is undefined, name is undefined" although "this" reference to car object because of implicit binding but the details' function doesn't follow that rule and defaults to global "this" where brand and name are undefined however, changing the details function to arrow function logs "the brand of the car is Toyota name is Lexus". arrow function uses lexical binding, meaning they inherit "this" keyword from their surrounding scope. here the "this" keyword inside the carBrandDetails refers to car object.

with the above listed rules, you can easily identify the value of the "this" keyword in javascript.