Understanding “this” in JavaScript by focusing on “where” and “how” a function is invoked
Tags: javascript, es6, frontend
Published: 2020-09-20 00:39:47

---
title: Understanding “this” in JavaScript by focusing on “where” and “how” a function is invoked
published: true
description: 
tags: javascript, es6, frontend
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9uswyhg7ue2reopqtxql.jpg
---

In this article I talk about what I've learned about how to know where `this` points to in a given function. Basically this is me sharing with you, in my own words how to do so.

And yes, I did that weird drawing at the top 😀

Firstly, it is important to understand that the `this binding` is not determined when a function is declared, instead, it is determined by where that function is invoked, and also based on how that function was invoked.


## **Step 1: WHERE**

The first thing we need to do is find where the function was invoked in our program. It could have been invoked from either the **global execution context** or from a **local execution context** , and the only way to find our function's **call-site** (besides watching directly in our code) is by looking at the [call stack](https://www.codementor.io/@diegopalacios/what-happens-when-javascript-is-initially-executed-xf2wbef61). Here's a very simple example that you can try in the console in order to see the stack. 

First, copy and paste the following code in your browser's console:

```javascript
function baz() {
    bar()
}

function bar() {
    foo()
}

function foo() {
    debugger
}

baz()
```

Then, in the **devtools**, under the sources tab, and then under the *Call Stack* section, you will see a list of functions. This way we can know for sure that **foo()** `call-site` is **bar()** , and **bar()** `call-site` is **baz()**, and finally **baz()** `call-site` is the *global execution context*, which in this case is shown as **anonymous**.

```
foo         (VM431:10)
bar          (VM431:6)
baz          (VM431:2)
(anonymous) (VM431:13) 
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hzi4ywqqc0zrjb8iphw1.png)

Now that we know how to find our function's call-site **(where)** , let's talk about the set of rules that determine the `this binding` **(how)** .

## **Step 2: HOW**

When a function is invoked, a new **Local Execution Context** is created. That **Local Execution Context** has information about the function (its place in the call stack, the arguments length and - among other things - a property called `this`).

The value of `this` (what object is it pointing to) is determined based on **how** the function is invoked. 

We can invoke our functions in 4 different ways, following 4 different rules, namely: 

* Default Binding
* Implicit Binding
* Explicit Binding
* New Binding

*Extra: I will also talk about how the `this binding` is determined on arrow functions.*


### **Default Binding**

```javascript
var x = 20

function foo() {
  console.log(this.x)
}

foo.x = 40

foo()  // 20 

```

A `default binding` is made when we do a regular function call, like we did here with `foo()`. In `non-strict` mode the `this binding` will reference the **global object**, but on `strict mode` it will be `undefined`.

It's worth mentioning that in the first line we declare a variable `x` and assign the value of 20. And this is like doing `window.x = 20`. Long story short, a property is created in the **global object**, and this is the reason why `this.x` is 20.

When `foo` is invoked, something like this happens under the hood:

```javascript
foo.call(window)   // non-strict

foo.call(undefined)   // strict
```

Even though we will revisit this subject later in one of the 4 rules, I'll briefly explain what's the `call()` method doing here: *The `call()` method is explicitly setting to what object `this` will be bound to.*


### **Implicit Binding**

When we invoke a function in the context of an object, `this` will point to that object. Let's take a look at the following code:

```javascript
var x = 20 

const myObj = {
  x: 50,
  foo: function() {
     console.log(this.x)
  }
}

myObj.foo() // 50
```

I would like to clarify that the anonymous function declaration in `myObj.foo` (aka method, since it is declared inside an object) does not belong to `myObj`. Remember that since functions are `callable objects`, they are assigned by reference (like all objects are), unlike the primitive values, which are assigned by copy. 

In order to illustrate my point, consider the following code:

```javascript
var x = 20 

const myObj = {
  x: 50,
  foo: function() {
     console.log(this.x)
  }
}

myObj.foo()  // 50

const foo = myObj.foo
foo()  // 20

```

When we declare `const foo`, we assign a reference to the same function `myObj.foo` is pointing to, and then, by doing a stand-alone invocation of `foo`, the default binding rule is applied, and since we're not using `strict-mode`, `this` will point to the `global object`, in this case, the `window`.

As you can see, and like I said before, the binding of `this` is not determined when the function is declared, but when the function is invoked and most importantly on how that function is invoked.


### **Explicit Binding**

All functions have access to three different methods that allow us to invoke them and explicitly set the object that `this` will be bound to. I'm talking about the `call()`, `apply()` and `bind()` methods. 

Consider the following code:

```javascript
const obj = {
  x: 'Hi there'
}

function foo(name, age) {
  console.log(
    `${this.x}, my name is ${name}, and I'm ${age} years old`
  )
}

foo.call(obj, 'Diego', 31)  
// 'Hi there, my name is Diego, and I'm 31 years old'

foo.apply(obj, ['Diego', 31])  
// 'Hi there, my name is Diego, and I'm 31 years old'

const bar = foo.bind(obj, 'Diego', 31)
bar()  // 'Hi there, my name is Diego, and I'm 31 years old'

```

Let's talk about each of the call methods in our snippet:

* **call()** : Invokes and receives (as its first argument) an object that will explicitly be bound to `this`. It also receives the function's arguments separated by a comma.

* **apply()** : It does the same thing as **call()**, but the only difference is that the arguments are passed inside an array.

* **bind()** : It's also similar to **call()** but instead of immediately invoking the function, it returns a function with `this` bound to the object passed as its first argument. In this snippet we store the returned function in a `const` and below that we make the invocation.


### **New Binding**

A function invocation with the `new` keyword at the beginning is referred to as a `constructor call`. Let's now consider the following code snippet:

```javascript
function foo(name, age) {
   this.name = name
   this.age = age
}

const bar = new foo('Diego', 31)

console.log(
`My name is ${bar.name}, and I'm ${bar.age} years old`
) 

// My name is Diego, and I'm 31 years old

```

When we do a `constructor call` on the foo method, this is what happens:

1. First, it creates and return a new object. Something like `Object.create({})`.

2. `this` will point to the newly created object, which in this case has a reference to that object in `bar`.

3. And lastly, the newly created object is linked to the function's prototype. In other words, the `bar` object delegates its `[[Prototype]] / __proto__` to the `foo`'s `prototype` object.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ic7weq6n0ql2cpd94kjj.png)

Just as a refresher, all functions have a `prototype` object. It only has one property, `constructor` , which happens to be a reference to the function itself.

```javascript
foo.prototype
/*
Output:

{ constructor: ƒ foo(name, age), __proto__: Object.prototype }
*/

bar.__proto__    

// or

Object.getPrototypeOf(bar)

/* 
Output:

{ constructor: ƒ foo(name, age), __proto__: Object.prototype }
*/

foo.prototype === bar.__proto__  // true
foo.prototype === Object.getPrototypeOf(bar) // true
```

These are the 4 rules that will determine the `this binding` of a function. So now we know the questions we need to ask ourselves in order to know where `this` is pointing, namely:

* **where** has the function been invoked?
* **how** the function was invoked?


### **Arrow functions and `this`**

But there's one more thing to consider...

Unlike the 4 rules above, the `this binding` in arrow functions is determined by its parent scope. In other words, the `this binding` of an arrow function is the same as its container function:

```javascript
var name = 'Global'

function foo() {

  const bar = () => {
      console.log(this.name)
  }
  
  return bar
}

const obj = {
  name: 'Diego'
}

const fn = foo()
fn()  // 'Global'

const fn2 = foo.call(obj)
fn2()  // 'Diego'

```

When the `foo` function is invoked, the arrow function will inherit the `this` from `foo`.

In `const fn = foo()` since `foo()` invocation is a regular/normal function call, the **Default Binding** rule is applied, so in this case the foo's `this` points to the `window` object (if we are on `strict mode` it will be `undefined`).

But, in `const fn2 = foo.call(obj)` , the **Explicit Binding** rule is applied, since we're explicitly setting the obj that will be bound to foo's `this`, which is the `obj` object. 

And even if we do a `fn2()` (invoking our returned arrow function) which according to the 4 rules is a **Default Binding**, it will ignore those rules, and use the `this binding` of foo's invocation, in this case `obj`.


### **Final words**

Like I said at the begging, this post is me writing in my own words what I learned from the YDKJS book series, specifically the from the `this & Object Prototypes` book from [Kyle Simpson](https://me.getify.com/). I fully recommend all the books from the series.