DEV Community

Heet Shah
Heet Shah

Posted on • Edited on

What is THIS keyword in JavaScript? - Part 1

You will encounter this more often and as a developer, it is important to understand how it works.

This topic will be divided into two articles:

  1. What is this keyword and different types of binding.
  2. Arrow function and this keyword.

this keyword is nothing but a reference to an object. The value of the reference depends upon the current execution context (means how and by whom the method is called). I know this sounds confusing so let us take an example and I will explain to you how to find to whom this keyword is referring.

let fullName = function () {
    return `${this.firstName} ${this.lastName}`;
};
let Person = function (firstName, lastName) {
    return {
        firstName,
        lastName,
        fullName
    };
};

let person1 = Person("Dwight", "Schrute");
let person2 = Person("Jim", "Halpert");

console.log(person1.fullName()); // Dwight Schrute
console.log(person2.fullName()); // Jim Halpert
Enter fullscreen mode Exit fullscreen mode

You may have got the answer but it is also important to understand how? It's easy and I personally remember with this thumb-rule - Always look at the owner object(by whom the method was called) or look at the left of the dot. Here, in the first output person1.fullName() the object viz. left to the dot is person1 so this inside the fullName method will refer to the person1 object and will return it's first and last name. This type of binding is called implicit binding and will explain more about it later.
Now we have understood some basics about this keyword, let's learn about different types of binding.

1. Implicit binding

You will see this type of binding in most of the codebases and it's important to understand how it works. Thumb-rule which we had discussed earlier applies to this type of binding. Let us take an example to see how our thumb-rule works for the below type of scenario:

let fullName = function () {
    return `${this.firstName} ${this.lastName}`;
};
let person1Friend= {
    firstName: "Angela",
    lastName: "Martin",
    fullName
}
let person2Friend = {
    firstName: "Pam",
    lastName: "Beesly",
    fullName
}
let Person = function (firstName, lastName, friend) {
    return {
        firstName,
        lastName,
        fullName,
        friend
    };
};

let person1 = Person("Dwight", "Schrute", person1Friend);
let person2 = Person("Jim", "Halpert", person2Friend);

console.log(person1.friend.fullName()); // Angela Martin
console.log(person2.friend.fullName()); // Pam Beesly      
Enter fullscreen mode Exit fullscreen mode

So look at "left to the dot", this will now refer to a friend object therefore fullName method will return the first and last name of the person's friend.

Note: In case if there is nothing to the left of the dot then this will bind itself to a global or window object in non-strict mode. This is known as Global/Default binding and we will discuss more about it later.

2. Explicit Binding / Fixed Binding

In some scenarios, we as a developer want to specifically inform the javascript engine to bind the current execution context with a certain object. You may have heard about call(), apply() and bind() method. These methods are available to every function and let us discuss in detail with some examples.

  • call

This method accepts the first argument as the object to which it has to refer or point to. Rest arguments will be pass as arguments to the function.

const TheOffice = {
    characters: ["Jim Halpert", "Michale Scott", "Dwight Schrute"],
};
const Friends = {
    characters: ["Joey Tribbiani", "Rachel Green", "Chandler Bing"],
};
const SiliconValley = {
    characters: ["Jin Yang", "Richard Hendricks", "Jared Dunn"],
};

const displayCharacters = function (series, channel) {
    this.characters.forEach(function (character) {
        console.log(`${character} is featured in ${series} aired on ${channel}`);
    });
};

displayCharacters.call(TheOffice, "The Office", "NBC"); 
/*
Output:
Jim Halpert is featured in The Office aired on NBC
Michale Scott is featured in The Office aired on NBC
Dwight Schrute is featured in The Office aired on NBC
*/
displayCharacters.call(Friends, "Friends", "NBC");
/*
Output:
Joey Tribbiani is featured in Friends aired on NBC
Rachel Green is featured in Friends aired on NBC
Chandler Bing is featured in Friends aired on NBC
*/
displayCharacters.call(SiliconValley, "Silicon Valley", "HBO");
/*
Output:
Jin Yang is featured in Silicon Valley aired on HBO
Richard Hendricks is featured in Silicon Valley aired on HBO
Jared Dunn is featured in Silicon Valley aired on HBO
*/
Enter fullscreen mode Exit fullscreen mode

So from above, we can see that each object is mapped and displays the characters present in that series. We also have passed two arguments (series and channel name) which are then passed to displayCharacters.

  • apply

The apply() method is similar to call(). The difference is that the apply() method accepts an array of arguments instead of comma-separated values. The below example will explain when can we use the apply method.

const person = { name: "John Green" };
const cars = ["Aston Martin", "Maserati", "BMW", "Alfa Romeo"];

const showCars = function (car1, car2, car3, car4) {
    console.log(`${this.name} owns ${car1}, ${car2}, ${car3} and ${car4}`);
};

showCars.apply(person, cars); /*John Green owns Aston Martin, Maserati, BMW and Alfa Romeo */
Enter fullscreen mode Exit fullscreen mode

If we had to use call method for the above example then we have to pass each car name as an argument as shown below:

showCars.call(person, cars[0], cars[1], cars[2], cars[3]);
Enter fullscreen mode Exit fullscreen mode
  • bind

This is same as call method but instead of executing it immediately, it returns the function which can be called later.

const TheOffice = {
    characters: ["Jim Halpert", "Michale Scott", "Dwight Schrute"],
};
const displayCharacters = function (series, channel) {
    this.characters.forEach(function (character) {
        console.log(
            `${character} is featured in ${series} aired on ${channel}`
        );
    });
};

let showTheOfficeCharacters = displayCharacters.bind(
    TheOffice,
    "The Office",
    "NBC"
);
showTheOfficeCharacters();
/*
Output:
Jim Halpert is featured in The Office aired on NBC
Michale Scott is featured in The Office aired on NBC
Dwight Schrute is featured in The Office aired on NBC
*/
Enter fullscreen mode Exit fullscreen mode

3. Global/ Window / Default binding

In this type of binding, this keyword will by default refer to the global execution context in non-strict mode if it is not found in the current execution context. Yes, this is weird but this is how JavaScript works. Let us see the below example by what do I mean global binding.

function displayInfo () {
  console.log(`My name is ${this.name} and I am ${this.age} years old`)
}
const user = {
  name: 'John Green',
  age: 34
}
displayInfo() // My name is undefined and I am undefined years old
Enter fullscreen mode Exit fullscreen mode

Why are we seeing undefined? Yes, this is how it works since we haven't bind it to any object this will by default bind itself to global and also it is in non-strict mode so this.name and this.age will show undefined.

Note: If we run the above code in strict mode then it will throw an error as this.name and this.age is not defined globally. This is one of the reasons why developers recommend using strict mode in your project so that you can avoid unexpected output.

this.name = "Alex Carey";
this.age = "30";

function displayInfo () {
  console.log(`My name is ${this.name} and I am ${this.age} years old`)
}
const user = {
  name: 'John Green',
  age: 34
}
displayInfo() // My name is Alex Carey and I am 30 years old
Enter fullscreen mode Exit fullscreen mode

Here since we have defined this.name and this.age at the global level displayInfo() will show that value.

4. New Keyword in JavaScript

You would have definitely invoked a function using the new keyword. Under the hood what javascript does is it creates a new blank object and this refers to that object.

function Person(name, age) {
  /*
    JavaScript creates a new object
    called `this` which delegates to the Person prototype
    on failed lookups. If a function is called with the
    a new keyword, then it's this new object that interpreter
    created that this keyword is referencing.
  */

  this.name = name
  this.age = age
}

const person1 = new Person('John Green', 34)
Enter fullscreen mode Exit fullscreen mode

That's it! You have now learned about what is this keyword in javascript and it's different types of binding. As mentioned earlier we will cover Lexical binding (what this keyword means in arrow function) in the next article.

PS: After reading this article I would suggest you play around with this keyword using your favorite editor.

Top comments (0)