# "this" in Javascript

`this` refers to the object on which a function (method) is called – hence `this` is defined by the execution context. The value of `this` really depends on **how and where** a function is called. To better understand the execution context, we should first understand how functions are invoked.

> To understand what `this` refers to, always think about how and on which object a function or method is called. 

>For indirectly executed functions, console.log(this) can help you understand the value that will be assigned.

Javascript has **4** main invocation types:

1. function invocation: myFunction('Hello World!')
2. method invocation: console.log('Hello World!')
3. constructor invocation: new Pet('Dog', 2)
4. indirect invocation: alert.call(undefined, 'Hello World!')
5. Arrow function: this is not an invocation type but a new EX2016 way to declare a variable


## 1. 'this' in Function invocation

Function invocation is performed when an expression that evaluates to a function object is followed by parentheses. For instance,`parseInt('18')`, `hello('World')` or `function() {...}` are simple example function invocation.

> `this` is the **global object** in a function invocation. In a browser, the global object is window object.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633680494707/XPKV8TXFT.png)

```
function sum(a, b) {
  console.log(this === window); // => true
  this.myNumber = 20; // add 'myNumber' property to global object
  return a + b;
}
// sum() is invoked as a function
// this in sum() is a global object (window)
sum(15, 16);     // => 31
window.myNumber; // => 20
```

At the time sum(15, 16) is called, JavaScript automatically sets `this` as the **global** object (window in a browser).

When `this` is used outside of any function scope (the topmost scope: global execution context), it also equals to the global object:

```
console.log(this === window); // => true
this.myString = 'Hello World!';
console.log(window.myString); // => 'Hello World!'

<!-- In an html file -->
<script type="text/javascript">
 console.log(this === window); // => true
</script>
```

Function invocation also happens on anonymous functions. For instance in a function we add a setTimeout with an anonymous function inside.

```
function logMe() {
   setTimeout( function() {
      console.log(this === window); // => true
   },1000);
}
```

However in 'strict mode', `this` is not the window but instead undefined.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633680577877/Ars58S-Qk.png)

An example of a function called in strict mode:

```
function multiply(a, b) {
  'use strict'; // enable the strict mode on this function
  console.log(this === undefined); // => true
  return a * b;
}
```


## 2. 'this' in Method invocation

A method is a function stored in a property of an object. For example:

```
const myObject = {
  // helloMethod is a method
  helloMethod: function() {
    return 'Hello World!';
  }
};
const message = myObject.helloMethod();
```

`helloMethod` is a method of `myObject`. Use `myObject.helloMethod` to access the method.

> Understanding the difference between function invocation and method invocation is important! The method invocation requires a **property accessor** form to call the function (`obj.myFunc()` or `obj['myFunc']()`), while function invocation does not (`myFunc()`).

```
obj.myMethod();                     // method invocation
[1,2].join(',');                             // method invocation
const func = obj.myMethod; // function declaration with an method
func();                                     // function invocation
parseFloat('16.6');                  // function invocation
isNaN(0);                                // function invocation
```
> `this` is the object that owns the method in a method invocation. When invoking a method on an object, `this` is the *object that owns the method*.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633681493533/ILGVkskDB.png)

```
const calc = {
  num: 0,
  increment() {
    console.log(this === calc); // => true
    this.num += 1;
    return this.num;
  }
};
// method invocation. this is calc
calc.increment(); // => 1

const myDog = Object.create({
  sayName() {
    console.log(this === myDog); // => true
    return this.name;
  }
});
myDog.name = 'Milo';
// method invocation. this is myDog
myDog.sayName(); // => 'Milo'
```

## 3. `this` in Constructor invocation

Constructor invocation is performed when `new` keyword is followed by an expression that evaluates to a function object with parentheses with parameters if any. Example of constructor invocation: `new Pet('Dog', 2)`

Starting ECMAScript 2015, JavaScript allows to define constructors using `class` syntax:

```
class City {
  constructor(name, traveled) {
    this.name = name;
    this.traveled = false;
  }
  travel() {
    this.traveled = true;
  }
}
// Constructor invocation
const paris = new City('Paris', false);
paris.travel();
```

`new City('Paris')` is a constructor invocation. The object’s initialization is handled by a special method in the class: `constructor`, which has `this` as the **newly created object**.

The role of the constructor function is to initialize the instance. A constructor call creates a new empty object, which inherits properties from the constructor’s prototype. The constructor initializes the object with data that comes from constructor arguments, sets up initial values for properties, attaches event handlers, etc.

When a property accessor, for instance `City('Paris', false)`, is preceded by `new` keyword, JavaScript performs a **constructor invocation**, but not a method invocation.

> `this` is the newly created object in a constructor invocation. The context of a constructor invocation is the newly created object.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633685500286/hqLGSQ3Koz.png)

Example:

```
class Bar {
  constructor() {
    // this is bar Instance
    this.property = 'Default Value';
  }
}
// Constructor invocation
const barInstance = new Bar();
barInstance.property; // => 'Default Value'
```


## 4. `this` in Indirect invocation

Indirect invocation is performed when a function is called using `myFun.bind()`, `myFun.call()` or `myFun.apply()` methods.  `.call()` and `.apply()` methods are used to invoke the function with a configurable context.

`myFunction.bind(thisArg[, arg1, arg2, ...)` accepts the first argument `thisArg` as the context and an optional list of arguments arg1, arg2, ... to bound to .bind() returns a new function which context is bound to `thisArg` and arguments to arg1, arg2, ....

Example: 

```
function multiply(number) {
  'use strict';
  return this * number;
}
// create a bound function with context
const double = multiply.bind(2);
// invoke the bound function
double(3); // => 6
double(10); // => 20
```

The multiply.bind(2) returns a new function object double, which is bound with number 2. multiply and double have the same code and scope.

> `this` is the first argument of `myFunc.bind(thisArg)` when invoking a bound function.

The role of .bind() is to create a new function, which invocation will have the context as the first argument passed to .bind(). It is a powerful technique that allows creating functions with a predefined `this` value. 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633686944401/pkq0JTVJs.png)

`myFunction.call(thisArg, arg1, arg2, ...)` accepts the first argument `thisArg` as the context of the invocation and a list of arguments `[arg1, args2, ...]` that are passed as arguments to the called function.

`myFunction.apply(thisArg, [arg1, arg2, ...])` accepts the first argument `thisArg` as the context of the invocation and an array of arguments `[arg1, args, ...]` that are passed as arguments to the called function.

> `this` is the first argument of .call() or .apply() in an indirect invocation. `this` in indirect invocation is the value passed as first argument to .call() or .apply().

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633686458053/uq9yfBCDF.png)

Example of .call() and .apply(): 

```
const rabbit = { name: 'White Rabbit' };
function concatName(string) {
  console.log(this === rabbit); // => true
  return string + this.name;
}
// Indirect invocations
concatName.call(rabbit, 'Hello ');  // => 'Hello White Rabbit'
concatName.apply(rabbit, ['Bye ']); // => 'Bye White Rabbit'
```
> .apply and .call methods can be very useful when on `strict mode` whereby the `this` is either `window` or `undefined`.

## 4. `this`in Arrow function

Arrow function is designed to declare the function in a shorter form and lexically bind the context.

It can used the following way:

```
const hello = (name) => {
  return 'Hello ' + name;
};
hello('World'); // => 'Hello World'
// Keep only even numbers
[1, 2, 5, 6].filter(item => item % 2 === 0); // => [2, 6]
```

Arrow functions have a light syntax, don’t have the verbose keyword `function`. When the arrow function has only 1 statement, you could even omit the `return` keyword.

> `this` is the enclosing context where the arrow function is defined. The arrow function doesn’t create its own execution context but takes this from the outer function where it is defined.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633693386853/1r-R_rT4j.png)

Example:

```
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  log() {
    console.log(this === myPoint); // => true
    setTimeout(() => {
      console.log(this === myPoint);      // => true
      console.log(this.x + ':' + this.y); // => '95:165'
    }, 1000);
  }
}
const myPoint = new Point(95, 165);
myPoint.log();
```

## How to control `this`

`this` can be controlled with three main techniques: 
1. Helper variable on outer functions/objects like `const that = this` 
2. bind(), call(), apply() methods
3. Arrow functions (as they don't care about `this`)

1. that = this

```
class Person {
  constructor() {
    this.age = 31;
  }

  greet() {
    console.log('My age: ' + this.age); // this comes from the constructor
  }

  greetWithDelay() {
    const that = this;
    setTimeout(function() {
      console.log(this); // window
      console.log('My age: ' + that.age); // 31 for that.age
    };
  }
}

const max = new Person();
max.greet();
max.greetWithDelay();
```

2. .bind() method

```
class Person {
  constructor() {
    this.age = 31;
  }

  greetWithDelay() {
    setTimeout(function() {
      console.log(this); // window
      console.log('My age: ' + this.age); // check the .bind method
    }.bind(this), 1500); // this is on the outer scope on greetWithDelay() instead of the setTimeout()
  }
}

const max = new Person();
max.greetWithDelay();
```

3. arrow function

```
class Person {
  constructor() {
    this.age = 31;
  }

  greetWithDelay() {

    setTimeout(() => { // arrow function used here
      console.log(this); // this from constructor
      console.log('My age: ' + this.age); // 31
    }, 1500);
  }
}

const max = new Person();
max.greetWithDelay();
```
