Misconceptions of `this`
Tags: javascript, this
Published: 2021-07-01 23:55:50

Hello friends, 


let's start with what __is not__ `this`... 

`this` isn't bound to :

1- __the object `this` appears within.__

2- __the function `this` appears within.__

3- __a new instance of the function `this` appears within.__


<hr/>

The keyword `this` itself doesn't have a value. JS interpreter binds the value of `this` when its parent function gets invoked. but would you always trust the JS interpreter to bind the value of `this` to the `right object` automatically? ... I wouldn't.

In other words, when someone shows you a code and asks you:
> what is the value of `this` here ?

the right answer would be:
> show me where the parent function is invoked.

I'll try to sum it up in 5 scenarios:

##  1. The global object or undefined
If the function is called with no context:
```js
function displayName() {
  console.log(this);
}
displayName(); // {}
```
In the code above, the value of `this` inside `displayName()` is either the `global object` or, if in strict mode, it's `undefined`.
<hr/>

## 2. A context object
If the function is a method of an object:
```js
const player = {
  name: "Mohamed",
  displayName: function () {
    console.log(this.name);
  },
};
player.displayName(); // "Mohamed"

```
In the code above, the value of `this` inside `displayName()` will refer to `player` which actually makes sense because you called the method `displayName()` on the object `player`. that invocation bound the object `player` to `this` inside of the method. good job JS interpreter. 
<hr/>

## 3. A new object

```js
function Square(color) {
  this.color = color;
}
const redSquare = new Square("red");
```
let's see what the keyword `new` does behind the scenes.

without using the keywords `new` and `this`, you will have to create and return the object manually 
```js
function Square(color){
 let obj = {}
 obj.color = color
 return obj
}
const redSquare = Suare("red");
```
the keyword `new` actually creates the object for you and binds that object to `this`... then return it 
```js
function Square(color){
 ̶l̶e̶t̶ ̶t̶h̶i̶s̶ ̶=̶ ̶O̶b̶j̶e̶c̶t̶.̶c̶r̶e̶a̶t̶e̶(̶S̶q̶u̶a̶r̶e̶.̶p̶r̶o̶t̶o̶t̶y̶p̶e̶)̶; //{}
 this.color = color;
 ̶r̶e̶t̶u̶r̶n̶ ̶t̶h̶i̶s̶; 
}
const redSquare =new Square("red"); 
```
In the code above, the value of `this` inside the function is a newly created empty object. 
<hr/>

## 4. A specified object

So far we have been saying that JS interpreter does all the work automatically for us... do we have control over the value of this ? 
Actually, YES we do
we have two 3 methods to change the value of `this` 
### .call() and .apply() methods
```js
const player = {
  name: "Mohamed",
  displayName: function () {
    console.log(this.name);
  },
};

const anotherPlayer = { name: "ahmed" };
player.displayName.call(anotherPlayer); // "ahmed"
```
same as
```js
player.displayName.apply(anotherPlayer)
```
In the code above, the value of `this` inside `displayName()` will refer to `anotherPlayer` since the first parameter of `call()` or "apply() is to explicitly set what `this` refers to.

### .bind()

`bind()` method is a little bit different because it returns the same function after it sets the value of `this` to whatever you want 

```js
const player = {
  name: "Mohamed",
  displayName: function () {
    console.log(this.name);
  },
};

const anotherPlayer = { name: "ahmed" };
const displayName = player.displayName.bind(anotherPlayer);
displayName(); // "ahmed"
```
In the code above, `bind()` set the value of `this` inside `player.display` to `anotherPlayer` and returned a whole new function.


.... wait what ... why would I use `bind()`...I'll stick to `call()` and `apply()`.

let's say you have this code, a simple function that takes a callback and call it twice.
```js
const player = {
  name: "Mohamed",
  displayName: function () {
    console.log(this.name);
  },
};

function callTwice(cb) {
  cb();
  cb();
}

callTwice(player.displayName);

```
what do you expect ?? you passed the right function... but look where it's invoked ! 
the output would be according to rule number # 1 
```js
undefined
undefined
```
In the code above, the value of `this` will be the global object because that's how its parent function got invoked. 

Don't worry... `bind()` to the rescue 
```js
const callback = player.displayName.bind(player);
callTwice(callback); // "Mohamed" 
                     // "Mohamed"
```

<hr/>

## 5. `this` inside arrow function

With regular functions, the value of `this` is set based on how the function is called. With arrow functions, the value of `this` is based on the function's surrounding context. In other words, the value of `this` inside an arrow function is the same as the value of `this` outside the function then apply the rules we mentioned earlier.

## for more readings 
1- [Apply MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)

2- [Call MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)

3- [Bind MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind)