Understand "this" on JavaScript right now
Tags: javascript, this, programming, functions
Published: 2021-04-02 13:13:11

**this** keyword has lead to a lot of bugs and troubles over the years. Nowadays there are a lot of post trying to explain how this works but I'll try to give my bit on this topic.
Before enter the good stuff we need to review a little of concepts to understand how JavaScript manages *this* depending on the context, so...

#What we need to know before? :thinking:

If you are familiar with the following terms maybe you can skip this section:
* Arrow functions 
* Nested functions
* Methods

## Arrow functions :bow_and_arrow:

Arrow functions are a new type of functions introduced in ES6. Basically they are a shortcut way of writing functions.
Here we can see their syntax:
```javascript
const square = (a, b) => a * b;
```
And the same with regular functions
```javascript
const square = function(a, b) { return a * b };
```
## Nested functions :dolls:

![Nesting gif](https://media.giphy.com/media/LQ34HLnIOUrzmXvvgI/giphy.gif)

Nested functions are nothing more than functions inside another functions.
This functions can access the variables defined inside the parent function and are only visible within the scope of the parent function.
```javascript
function parent(){
    function nestedFunction(){
        console.log('Hey! I am a nested function');
    }
    nestedFunction();
}
```
## Methods :package:

Methods are functions that are declared inside an object. This means that method are functions that need to be executed with an object as context.
```javascript
const obj = {
    x: 0,
    y: 0,
    square: function() {
        return this.x * this.y;
    },
}
```
Here we have a function that uses the object properties to get the square of these numbers. The function cannot work on its own.

# Let's go with this keyword :muscle:

![Strong Bob](https://media.giphy.com/media/D7z8JfNANqahW/giphy.gif)

We'll classify how this works like in the previous section.

#Regular functions

Functions by default are bound to the global object.
```javascript
function writeGlobal(){
    console.log(this);
}
```
So *this* keyword in the previous example references to the global object.

We would bind *this* to another value (in these examples to a string object) using the following methods:
**Bind**
```javascript
let sayHello = function() {
    console.log(`Hello ${this}!`);
}
sayHello = sayHello.bind('Alex');
//Prints 'Hello Alex!'
sayHello();
```
*Note: We have to assign sayHello function again because bind returns the function bound, not modifies the original function object*

**Call**
```javascript
let sayHello = function() {
    console.log(`Hello ${this}!`);
}

//Prints 'Hello Alex!'
sayHello.call('Alex');
```

**Apply**
```javascript
let sayHello = function() {
    console.log(`Hello ${this}!`);
}

//Prints 'Hello Alex!'
sayHello.apply('Alex');
```

#Arrow functions

When we use arrow functions *this* doesn't have the global object bound, instead it inherits the *this* value of the context within they are. Let's see some code.

```javascript
let sayHello = function() {
    const getHelloPhrase = () => {
        return `Hello ${this}!`;
    }
    
    console.log(getHelloPhrase());
}

//Prints 'Hello Alex!'
sayHello.call('Alex');
```
Here, the arrow function uses the this value to generate a hello string. So when we bound the this value of sayHello function to 'Alex', the arrow function also has the this value bound to 'Alex'

#Nested functions

Nested functions works a little bit different as the previous example even though it looks pretty similar. Let's see some code before explaining.

```javascript
let sayHello = function() {
    const getHelloPhrase = function() {
        return `Hello ${this}!`;
    }
    
    console.log(getHelloPhrase());
}

//Prints 'Hello [object global]!'
sayHello.call('Alex');
```
Here we have a pretty similar code like before but we get a different result :worried:
Why?
Unlike arrow functions, nested functions don't inherit the *this* value of the context they are declared.

Like we saw before, with regular functions the value is bound to the global object, and since nested functions are regular functions inside an others, they have the same rules.
So if we want nested functions to have the same behavior as arrow functions we need to take the following approach.

```javascript
let sayHello = function() {
    let getHelloPhrase = function() {
        return `Hello ${this.toString()}!`;
    }

    getHelloPhrase = getHelloPhrase.bind(this);
    console.log(getHelloPhrase());
}

//Prints 'Hello Alex!'

sayHello.call('Alex');
```
Now we have the same behavior because we are binding the nested function to the this value of the parent function (like arrow functions).

## Methods
Earlier I've said that regular functions has this value as the global object by default, but there is an exception as we are going to see right now. So considering the following code.

```javascript
let person = {
    name: 'Alex',
    sayHello: function() {
        console.log(`Hello ${this.name}!`);
    }
}

//Prints 'Hello Alex!'
person.sayHello();
```
You may think that this would print *Hello undefined!* since the global object doesn't have a property called name, but with objects we have a different behavior. 

When we declare a function inside an object (a method) JavaScript automatically binds the object as the context of the function. So when we refer to *this* inside a method we are referring to the object that has the method. That explains why we cat get the property name of the person object with **this.name**.

The following code show a similar of what JavaScript does under the hood.

```javascript
let person = {
    name: 'Alex'
}

function sayHello() {
    console.log(`Hello ${this.name}!`);
}

//Prints 'Hello Alex!'
sayHello.call(person);
```

## So... If we use arrow functions instead of regular functions they behaves the same ? :thinking:

Wrong :x:

You should't use arrow functions as member functions. Why?
As seen earlier, arrow functions behaves a little different to regular functions. They inherits *this* from the scope within they are declared.

See [this page](https://www.section.io/engineering-education/how-to-use-javascript-arrow-functions-and-this-keyword/#:~:text=Arrow%20functions%20treat%20this%20keyword,have%20its%20own%20this%20context.&text=this%20in%20regular%20function%20always,the%20caller%20of%20the%20function) for more details.

# Conclusion

The behavior of *this* keyword may appear a little bit hard to learn at first but if you break down the different behaviors depending on the context maybe you'll understand better how this works.

This is the way I understood the behavior and I hope that maybe this post will help you to understand too.