The myth of JavaScript "this" Keyword
Tags: javascript, programming, beginners, tutorial
Published: 2021-08-13 18:58:50

## A practical example of “this”:

Suppose you have a nice house and the house number is 15 JS Road. Your wife wants to paint the house. So she tells you “We Need to paint **this** house”. Notice that she is referring to the house with a **this** keyword. She isn’t saying we need to paint 15 JS Road House. You both are already inside that house. So she is just saying **this** house. The meaning of **this** is so simple like that. Practically there is no difference between the **this** in real life and the **this** in JavaScript.

## Why the **this** keyword is in JS?

It helps a function to be reused in a different context.

There are 4 general rules. If you know these 4 rules you will have an idea about which object **this** is pointing at.

The rules are:
1. Implicit Binding
2. Explicit Binding
3. New Binding
4. Window Binding

I will now explain each rule with coding examples so that the topic will become more clearer.

**1. Implicit Binding**

```javascript
//example-1
const fahim = {
  name: "fahim",
  age: 24,
  printUserName: function () {
    console.log(this.name); // This ""this".name" refers to the name property of the current object it is in.
  },
};

fahim.printUserName(); //fahim
```
So here when we call printUserName function first we have to check if there is a “.” notation before it and if there is one then the “this” inside that function is referring to the object in which function is in. Here the function is inside the “fahim” object and it is a property of the object.

**2. Explicit Binding**
      **2.1 .Call()**

```javascript
////Explicit Binding(call)
 
const printName = function () {
  console.log(this.name); //fahim
};
 
const fahim = {
  name: "Fahim",
  age: 35,
};
 
printName.call(fahim);
```
So in Implicit Binding, we saw that the **this** keyword refers to the object it is in. Now, what happens if we take the function out of the object and declare it globally or in another context and try to print the **this.name**.There is a **.call()** function in JS which is nothing more than calling a function explicitly. **.call()** receives an object as the first parameter which means the function is called within the context of the object fahim here. So we are explicitly telling the definition of **this** inside the function. 

```javascript
const printName = function (v1, v2, v3) {
  console.log(`${this.name} is ${v1},${v2} & ${v3}`); //Fahim is Hardworking,All Rounder & Best Player
};

const fahim = {
  name: "Fahim",
  age: 35,
};

const v1 = "Hardworking";
const v2 = "All Rounder";
const v3 = "Best Player";

printName.call(fahim, v1, v2, v3);
```
Another use case of the **.call()** function is for its 2nd parameter it can take unlimited parameters. We can pass these parameters through the main function.

**2.2 .Apply()**

Now here we can see we have to pass a lot of parameters in the **.call()** function. So there is an alternative way of doing that. We can take all those parameters inside an array and pass that array inside a **.apply()** function. It does the same work as **.call()**.

```javascript
const printName = function (v1, v2, v3) {
  console.log(`${this.name} is ${v1},${v2} & ${v3}`); //Fahim is Hardworking,All Rounder & Best Player
};

const fahim = {
  name: "Fahim",
  age: 35,
};

const v1 = "Hardworking";
const v2 = "All Rounder";
const v3 = "Best Player";

const v = [v1, v2, v3];

printName.apply(fahim, v);
```

**2.3 .Bind()**

**.bind()** also does the same work as **.call()**. In  **.call()** we are directly calling the function. In  **.bind()** it returns an instance of a function. So if store it in a variable. Then we can call the variable and it will do the job.

```javascript
const printName = function (v1, v2, v3) {
  console.log(`${this.name} is ${v1},${v2} & ${v3}`); //Fahim is Hardworking,All Rounder & Best Player
};

const fahim = {
  name: "Fahim",
  age: 35,
};

const v1 = "Hardworking";
const v2 = "All Rounder";
const v3 = "Best Player";

const newName = printName.bind(fahim, v1, v2, v3);

newName();
```

So there is no confusion about the definition of **this** in Explicit Binding as we are explicitly defining it here.

**3. New Binding**

```javascript
function Person(name, age) {
  //let this = Object.create(null)
  this.name = name;
  this.age = age;
  console.log(`${name} is ${age} years old`);
  //return this
}

const Fahim = new Person("Fahim", 24);
const Ani = new Person("Ani", 24);
```
So here `Person` is a constructor function. It takes two parameters name and age. We created a `new Person` named Fahim. So by default JS creates an object named **this** inside the constructor function. So, `this.name` points to the new Object created by JS. The name `Fahim` and age `24` is passed to the constructor function and `this.name` and `this.age` receives it and returns the new object.

**4. Window Binding**

```javascript
 const PrintName = function () {
  console.log(this.name); //undefined
};
 
const sakib = {
  name: "Sakib",
};
 
PrintName();
```

When all 3 rules of binding don’t work then **this** will just point at the window. Hence we are getting `undefined`. We can prove that **this** is equal to window if we console.log it.

```javascript
const PrintName = function () {
  console.log(window===this);//true
  console.log(this.name); //undefined
};
 
const sakib = {
  name: "Sakib",
};
 
PrintName();
```

To get out of this weird behavior of getting undefined we can fix it by writing “use strict”. Then JS will show us the error.

```javascript
"use strict";
const PrintName = function () {
  console.log(this.name); //throws error
};
 
const sakib = {
  name: "Sakib",
};
 
PrintName();
```

## Note: 
The first 3 rules all are applied to normal JavaScript functions but if you are using **Arrow Function** then simply **Arrow Function** is not concerned with **this** and even **Arrow Function** is introduced to decrease the confusion of using **this** keyword. The value of **this** keyword in **Arrow Function** is whatever context the **Arrow Function** is in. It can be window/global, function or object.