'this' keyword in JavaScript
Tags: javascript, this, codenewbie, frontend
Published: 2023-06-29 16:49:36

> '**_this_**' in JavaScript can be very confusing, especially if you already know any Object Oriented Language (like **C++** or **Java**) because '**_this_**' in JavaScript behaves very different. 
> Let's dive right into it.

## Table of Contents
<a href='#thisid1'>1. What is 'this'?</a>
<a href='#thisid2'>2. What 'this' is not</a>
<a href='#thisid3'>3. Rules for 'this' - this all makes sense</a>
   - <a href='#thisid3.1'>3.1 Default Binding</a>
   - <a href='#thisid3.2'>3.2 Implicit Binding</a>
   - <a href='#thisid3.3'>3.3 Explicit Binding</a>
   - <a href='#thisid3.4'>3.4 new Binding</a>

<a href='#thisid4'>4. Rule Precedence</a>
<a href='#thisid5'>5. Wait there is more - Lexical 'this'</a>


---

<h2 id='thisid1'>1. <u>What is 'this'?</u> </h2>

'**_this_**' in JavaScript is a special keyword which refers to a object and gets automatically generated in the scope of the function.

It is a _runtime binding_ and it depends on the call site( where the function was invoked from ).

```js
var obj = {
    name : "Superman",
    printName : function(){
        console.log(`My name is ${this.name}.`)
    }
};

obj.printName(); // My name is Superman
```

Simple, isn't it? Well, not so fast. Check out this code.

```javascript
var obj1 = {
    name : "Superman",
    printName : function(){
        console.log(`My name is ${this.name}.`)
    }
};

var obj2 = {
    name : 'Batman'
}

obj1.printName.call(obj2); // My name is Batman.
```
How is obj2 able to access a property of obj1 and why is _**this**_ pointing to obj2 ? This post will clear all doubts one by one.

---

<h2 id='thisid2'>2. <u>What 'this' is not</u> </h2>

Before understanding what **_this_** actually means, we need to understand what _**this**_ is not.

### i. _**this**_ does not refer to itself
 
```js
// program to check how many times function was called
function fun(){
    this.count++;
}

/* We can add property to functions as they are also objects in js*/
fun.count = 0; 

for( var i=0; i<4; i++ )
    fun();

console.log(fun.count) // 0
```
Here, _**this**_ keyword inside fun() doesn't not refer to itself, as fun.count is still 0.
`Hint : this is pointing to global object. More on this later.`

### ii. _**this**_ doesn't refer to function scope.

```js
// this.a inside inner function doesn't
// refer to variable a of outer function
function outer(){
    var a = 4;
    function inner(){
        console.log(this.a);
    }

    return inner;
};

var f = fun1();
f(); // undefined
```
`Hint : Again, this is pointing to global object`
Does it mean that _**this**_ always points at global object ? 
The answer is NO, it was just a coincidence.

---

<h2 id='thisid3'>3. <u>Rules for 'this' - this all makes sense </u> </h2>

Now, we are about to dive deep into rules which define how this is binded to objects. There are 4 basic rules :-


![Types of binding in JS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ks47xuf15ffg3syxxmy5.png)

<h3 id='thisid3.1'>3.1 <u>DEFAULT BINDING</u> </h3>

By default this is binded to global object. If none of the other rules apply.

```js
var a = 'global';

function fun(){
    var a = 'local';
    console.log(this.a);
};

fun(); // global
```
In **strict-mode** global object is not available for default binding. So, **_this.a_** would result in **TypeError**.

```js
var a = 'global';

function fun(){
    "use strict"
    var a = 'local';
    console.log(this.a);
};

fun(); 
// uncaught TypeError: Cannot read properties of undefined (reading 'a')
```

---
<h3 id='thisid3.2'>3.2 <u>IMPLICIT BINDING</u> </h3>
 

In implicit binding '**_this_**' is binded to context object. Context Object is the object which contains the reference for the function called. It is also sometimes called owning or containing object.

> **Note :- Although the name suggests that the function is owned by the owning object(context object) it only contains the reference of the function. A function is never owned by any object.**

```js
var name = 'global';

function fun(){
    console.log(this.name);
}

var myObj = {
    name : 'myObj',
    fun : fun
}

fun(); // global -> due to default binding
myObj.fun() // myObj -> due to implicit binding

// here myObj is context object for function fun.
```
Some pitfalls in implicit binding.

_**a. Passing a reference**_
```js
var name = 'global';

function fun(){
    console.log(this.name);
}

var myObj = {
    name : 'myObj',
    fun
}

var f = myObj.fun; // only reference of fun is passed
f(); // global 
// actual call to fun is made without context object

// Remember object do not own a function
```
_**b. Only last/top level object property reference matters**_

```js
var name = 'global';

function fun(){
    console.log(this.name)
}

var obj1 = {
    name : 'obj1',
    fun
}

var obj2 = {
    name : 'obj2',
    obj1,
    fun
}

obj2.obj1.fun() // obj1
```

---
<h3 id='thisid3.3'>3.3 <u>EXPLICIT BINDING</u> </h3>


In this type of binding, we explicitly define which object **_this_** should bind to. This can be done with the help of  .bind(), .call() or .apply().

* **.call() ->** It is used to change the value of this inside a function and execute it with the arguments provided.
* **.apply() ->** It works just like .call() but takes arguments in a array.
* **.bind() ->** It takes object as first argument, rest of the arguments are used as default argument for the function.

Below code shows how these functions work.

```js
function introduce(city){
    console.log(`Hi, my name is ${this.name}. I live in ${city}. `)
}

var hero = {
    name : 'Spiderman'
}

introduce.call(hero,'New York');
introduce.apply(hero,['New York']);
// .call() and .apply() are immediately executed

var intro = introduce.bind(hero,'New York');
intro();
// new function (intro) is created with 'this' binded 
// to hero object. This function can be later executed.
```
**Hard Binding - Variation of Explicit binding**
Binding using .bind() is called hard binding.Code to implement our own .bind() function .

```js
function myBind(f,obj){
    return function(...args){
        f.apply(obj,args);
    }
};
// f -> function to be binded
// obj -> object 'this' should refer to
```

---

<h3 id='thisid3.4'>3.4 <u>new BINDING</u> </h3>

This type of binding is done with the help of new operator. Before we move forward let us make some things clear :-
- There are no class in JS, only objects. The class introduced in ES6 gives us false belief but under the hood they are all just functions and objects.
- There are no contructors in JS, they are not attached to any class.
- When functions are called with new operator in-front of them, then new object is created. It is called constructor call. Functions themselves are not constructors.

When functions are called with new operator then following things happen :

a. A new object is created out of thin air.
b. Newly created object is [[Prototype]]-linked to function.

> 
More on [[Prototype]] will be discussed in some other blog.

c. Newly created object is set as 'this' for the function call.
d. Function automatically returns a newly constructed object ( unless the function itself returns a object itself ).

```js
function fun(name,age){
    this.name = name;
    this.age = age;
    this.introduce = function(){
        console.log(`My name is ${this.name}. I am ${this.age} years old.`);
    }
};

var obj = new fun('Peter Parker',22);
obj.introduce();
```

---

<h2 id='thisid4'>4. <u>Rule Precedence</u> </h2>

i. Explicit Binding ( my own implementation myBind() )
ii. new Binding
iii. Explicit Binding ( internal implementation )
iv. Implicit Binding
v. Default Binding

> Note :- If null or undefined is passed as a 'this' binding parameter to call, bind or apply then default binding applies.

---
<h2 id='thisid5'>5. <u>Wait there is more - Lexical 'this'</u> </h2>

With the ES6, arrow functions were introduced which behaves differently than normal functions for this binding.

The arrow functions adopt the this binding from enclosing scope.

```js
function outer(){
    var inner = ()=>{
        console.log(this.name);
    }

    return inner;
}

var myObj = {
    name : 'myObj'
}

var inner = outer.apply(myObj);
inner(); // myObj
```
Arrow functions are useful when using callbacks to keep track of 'this'.

```js
var name = 'global';

var obj = {
    name : 'obj'
}

function exec(){
    setTimeout(() => {
        console.log(this.name)
    }, 1000);
};

exec.call(obj); // obj -> after 1000ms
/* 
Normal function as callback would 
print global after 1000ms as 'this' would
refer to global object
*/
```

In pre ES6 era, closure were used to keep track of this.

```js
var name = 'global';

var obj = {
    name : 'obj'
}

function exec(){
    var self = this;
    setTimeout(function(){
        console.log(self.name)
    }, 1000);
};

exec.call(obj); 
```

---
That is it for this blog. If you learned something from this blog then please like and share. If I made a mistake in this blog then please comment I would surely get back to it.
I am planning to write more blogs like this, so stay tuned.
Also, connect with me on [linkedin](https://www.linkedin.com/in/angshu-das-149784210/)