this with arrow functions in JS
Tags: javascript, react, webdev, jsinterview
Published: 2022-09-12 18:49:32

Hello reader, _this_ has always been one of the most confusing topics in JavaScript. If you have some previous knowledge of programming languages like Java, then understanding _this_ would again be a much more difficult task because your mind will have to fight between your existing knowledge of _this_ in other languages and learning new concepts in JavaScript even though they don't overlap at all.

Along with various other features and enhancements, ES6 brought arrow functions with it, and with the arrow functions introduction, the concept of _this_ started having a few more tweaks. To understand its concept and behaviour with arrow functions, some previous understanding of _this_ is definitely required. So, feel free to pause here and get some understanding of _this_ and then jump back to the topic.

## Table of contents:
1. [What are arrow functions?](#chapter-1)
2. [Understanding _this_ behaviour with arrow functions](#chapter-2)
   - In normal declaration
   - Defined inside a global object
   - In nested function call inside an object
   - Global functions bind to an object
3. [Conclusion](#chapter-3)

## What are arrow functions?<a name="chapter-1"></a>
Along with various other features, ES6 brought arrow functions with it too. They are newer, easier, and much cleaner ways of writing a function. They reduce the lines of code required to declare a function and come with small differences from the normal function declaration.
Let's compare the normal and arrow function declaration syntax first. 

```javascript
//normal function
function foo1(){
    return null
}
//arrow functions
const foo2 = () => {
    return null
}
//this can further be written in much simpler way
const foo = () => return null
```

As we see, arrow functions have much simpler syntax but the major difference is that arrow functions don't create their own binding but take up the binding of their parent object i.e. they inherit it from the parent scope (remember, the parent should be a non-function). To make it simpler, the arrow functions follow the same _this_ behaviour as it is in their parent. 
For normal functions, it totally depends on how and where they are called but for arrow functions, it depends on where they have been defined. In the above example, if we console _this_ inside both the functions then both _this_ will have a global object in them but the reason is quite different. Let's explore the same in next section.
 
## Understanding _this_ behaviour with arrow functions<a name="chapter-2"></a>

_this_ behaviour in arrow function can vary in different scenarios so let's break it into smaller parts and look through them.

- **In normal declaration**

```javascript
//normal function
function foo1(){
    console.log(this)
}
//with arrow functions
const foo2 = () => {
    console.log(this)
}

foo1()
foo2()
```
We saw in the above scenario, both consoles will print a global object(window object in case of browsers). Function foo1() is declared in a global context and is called in a global context, which is a normal function call. This means that the object calling foo1() is a global/window object(foo1() can also be called as a window.foo1()) and therefore, _this_ in having a value of the global object and hence, for a normal function call, _this_ always points to object calling that function. Whereas, foo2 has been declared in a global context whose _this_ always points to a global object and hence, in arrow function _this_ takes up the value of its parent binding, here global context and points to global/window object.

- **Defined inside a global object**

```javascript
//normal function
const obj1 = {
foo1 : function(){
        console.log(this)
     }
}
//with arrow functions
const obj2 = {
foo2 : () => {
        console.log(this)
     }
}

obj1.foo1()
obj2.foo2()
```
To call the normal function(foo1) inside obj1, we need to first access obj1 and then call foo1 through it. Hence, foo1 is not a normal function call and it has to be called through obj1. obj1 is an object and has created its own binding(_this_) and calling foo1 through obj1 makes _this_ inside obj1 to have all properties of obj1 only and not global/window object. Whereas, if we look at obj2 and foo2, then even though foo2 is declared as a key inside obj2 but still it will have a value of _this_ inherited from its lexical scope i.e. obj2 because as defined earlier, arrow functions inherit _this_ property from their parent and here obj2, which is parent object to foo2 has been declared in global/window context which has _this_ binding to global/window context and therefore, passes same this (global/window) to foo2.

- **In nested function call inside an object**

```javascript
//normal function call inside a method
const obj1 = {
        foo1 : function(){
                function foo2(){
                        console.log(this)
                }
                foo2()
        }
}
obj1.foo1()
//arrow function call inside a method
const obj2 = {
        foo3 : function(){
                const foo4 = () =>{
                        console.log(this)
                }
                foo4()
        }
}
obj2.foo3()
```

If you look closer at the code, then you can guess the output for both consoles as it has already been explained in the above two points. If you have taken a guess and it comes to be the same as what we will discuss, then congratulations to you. 

So, in foo2 the console will print the global/window object and the reason is in the definition above, any normal function call will always point its _this_ to the global/window object. Here, foo1 is a method to obj1 but foo2 is a normal function declared inside this method and hence _this_ pointing to global/window object. In the second scenario, foo4 is an arrow function that takes up the _this_ from its lexical scope so here, foo4 is lexically scoped to foo3, and foo3's _this_ is pointing to obj2 object, and hence foo4 will also point to obj2.

Here comes an interesting question. What if, foo3 is assigned with an arrow function instead of a normal function?

```javascript
const obj2 = {
        foo3 : () => {
                const foo4 = () =>{
                        console.log(this)
                }
                foo4()
        }
}
obj2.foo3()
```
In this case, it is certain that foo4 will always take up its _this_ value from the parent non-function which in this case is obj2, and since, obj2 is a global object whose binding is to a global object and hence foo4's _this_ will also point to global/window object. So, we can see a drastic change in the behaviour of functions depending if they are normal or arrow functions.

- **Global functions bind to an object**
```javascript
//normal function
function foo1(){
        console.log(this)
}
const obj1 = {
        name: 'Akansh'
}
const foo2 = foo1.bind(obj1)
foo2()

//arrow function
const foo3 = () => {
        console.log(this)
}
const obj2 = {
        name: 'Akansh'
}
const foo4 = foo3.bind(obj2)
foo4()
```
The given examples are no different from what we have seen earlier in the above examples. The only difference is that a global function is created which is now bound to another object and hence, the functions will now be treated as they were declared inside the object.

foo2 carries foo1 bind to obj1 and hence, calling foo2() is just like calling obj1.foo1()(if foo1 was declared inside obj1) and therefore, foo2 will have its _this_ pointing to obj1 only. Similarly, foo4 carries foo3 bind to obj2 but here foo4 _this_ points to global/window object because we now know that arrow function inside the object will have _this_ pointing to object's binding and here its global/window object.

## Conclusion<a name="chapter-3"></a>
For a normal function call, _this_ will always point to global/window object. A normal function defined inside an object will always takes up _this_ from the object written on adjacent left in the dot notation. Example: 

```javascript
const obj = {
    foo : function(){
         console.log(this)
    }
}
obj.foo()
//here, obj is the object calling foo and is on the adjacent left while writing in dot notation
``` 
For arrow function, the simplest explanation will be, _this_ will always inherit binding from its non-functional parent. If defined in global context, then _this_ in arrow function points to global/window object only.

I believe that the explanation was of some help to you and provided some value. If there is something I might have missed or you would like me to address or if there are some suggestions, feel free to comment and reach out.