Demystifying 'this' keyword in JS
Tags: javascript, beginners, webdev, discuss
Published: 2022-05-22 13:55:02

## Intro
_This_ keyword holds a special place in any object-oriented programming language and has been a mind-bender in Javascript. Needless to say, it has thus been a favourite topic of interviewers everywhere.
So, let's dive into what _this_ signifies and what its value is in different contexts.

**This** keyword returns the execution context of the function or code block in which _this_ has been used.
For example, if we perform the following operations in global context (outside of any functions), irrespective of 'strict' mode or not, we will get the results as such:

```
const name = "XYZ";
console.log(window.name); // Prints XYZ
console.log(this === window) // Prints true
```

### Function Context
In this case, the value of _this_ depends upon how the function is called.
When _not_ in 'strict' mode:
```
function f() {
  console.log(this === window)
}

f(); // prints true
```

In 'strict' mode, if _this_ is not set when entering an execution context, _this_ remains _undefined_:
```
function f() {
  'use strict';
  console.log(this===undefined);
}

f();  // prints true
```

`Note:` You can set _this_ using apply() or call() functions

```
const x = {val: 'x-val'};
const val = 'global-val';

function f() {
  console.log(this.val);
}

f() // prints 'global-val'
f.call(x) // prints 'x-val'
f.apply(x) // prints 'x-val'
```

In non-strict mode, if the value of _this_ (first argument to call() and apply()) is not an object, attempt is made to convert it into an object. 'null' or 'undefined' becomes the global object. Primitives like 1 or 'text' becomes object using respective constructors, Number and String in this example.

### Class Context
The behaviour of _this_ is similar in class and function contexts as class in javascript is just syntactical sugar. Basically, it is just a function.

Within the _constructor_ function of a class, the _this_ is just an ordinary object. All non-static methods of the class are added to the prototype of _this_ object.

In **derived classes**, there is no _this_ binding. One has to call `super()` function from the derived class. What this does is call the constructor of the base class and assign the _this_ object from that constructor.

```
this = new Base()
```
`Note:` Derived classes cannot return without calling `super()` or returning an object, because that will cause _ReferenceError_.

### Bind method
ES5 introduced the _bind_ method on functions. Calling `f.bind()` creates a new function with same body and scope as f. The _this_ however is bound to the first argument passed to the bind() function. Once _this_ is bound by using bind(), it cannot be changed.

```
function f() {
  console.log(this.val);
}

x = f.bind({val: 'new val'});
x(); // prints 'new val'

y = x.bind({val: 'change val'})
y(); // prints 'new val'

const obj = {val: 1, f:f, x: x, y: y};
obj.f(); // prints 1
obj.x(); // prints 'new val'
obj.y(); // prints 'new val'
```

### Arrow functions
In arrow functions, _this_ retains the value of the enclosing context's _this_. In global context, that would mean the global object. In function context, it will be determined as like we discussed in the sections above.

For example,

```
const obj= {
  x: function() {
    const y = () => this;
    return y;
  }
};

// calling x with obj context and setting its reference to f
const f = obj.x();

// Calling f would normally return window or global object or //undefined in strict mode
console.log(f() === obj) // true

// However, in this case above behaviour will not be true
const f = obj.x; // we are just taking the function

// Calling f from global context
console.log(f()() === obj) // false, this will equal global
```