What is THIS keyword in JavaScript? - Part 1
Tags: javascript
Published: 2020-11-02 14:00:24

> |What is THIS keyword in JavaScript? |
| --- |
| [Part 1 - What is this and it's different types of binding](https://dev.to/heet1996/what-is-this-keyword-in-javascript-part-1-2g9p)|
| [Part 2 - Arrow function and `this` keyword](https://dev.to/heet1996/what-is-this-keyword-in-javascript-part-2-7be)|  

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.

```JS 
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
```
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:

```js
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      
```
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.  
```js
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
*/
```
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.

```js
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 */
```
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:
```js
showCars.call(person, cars[0], cars[1], cars[2], cars[3]);
```

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

```js
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
*/
```
#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.

```js
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
``` 

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.  

```js
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
```
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.

```js
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)
```     

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.