How well do you know “this”?
Tags: javascript, programming, webdev, beginners
Published: 2021-02-28 01:07:45

<meta name="monetization" content="$ilp.gatehub.net/271431223"/>

## **What’s “this”?**

In the simplest of terms, the JavaScript keyword `this` refers to the object it belongs to on runtime, depending upon its **call-site** (where it is called).

However, understanding what it would refer to in any given context, requires a slightly deeper understanding of some relevant concepts, which will be covered in this article.

Just to start with, `this` can have the following values depending upon where it is accessed :

* ***By default*** : `this` refers to the `global` object.

* ***Inside a function*** : `this` refers to the `global` object. In `strict` mode, however, `this` will be `undefined`.

* ***Inside a method*** : `this` refers to the owner object. (A method is a function that belongs inside an object. In other words, it’s a function that’s an object’s property.)

* ***In an event***: `this` refers to the element on which the event was triggered.

* ***Inside an Immediately Invoked Function Expression (IIFE)*** : `this` refers to the `global` object. In `strict` mode, `this` will be `undefined`, just like any other function in a global context.

* ***Inside a Fat-Arrow function***: When a fat arrow `()=>` is used to define a function, it doesn’t create a new value for `this`, instead, it keeps referring to the same object it was referring to outside of the function.

This article hopes to give you an understanding of how these values are assigned to `this`, and how this knowledge can be utilized to suit our requirements.

## **Call-Site and Call-Stack**

As discussed in the last section, we got to know that this is a ***runtime-binding*** made for each function invocation, which entirely depends upon where exactly it was called.

This location in the code where the concerned function was called, is called the **call-site**. An understanding of determining the **call-site** is crucial towards understanding what this would be bound to, at any given point of the execution.

While finding the ***call-site*** is generally as simple as locating where a function was called from, it might not always be that clear because of certain coding patterns that might obscure it.

Hence, it’s important to think about the ***call-stack***, the stack of functions that have been called to get us to the current stage of the execution which we’re concerned with.

Let us take a simple example to illustrate how a ***call-stack*** and ***call-site*** could be determined.

{% gist https://gist.github.com/AnimeshPandey/3f49ddaa659fb049cd9979682ae74530.js %}


By following the chain of function calls in order, you can determine the **call-stack and call-sites.**

### * Tip for determining call-stack

Utilize the built-in JS `debugger` provided with any modern browser’s developer tools.

In the execution of any JS code, you can set a breakpoint by using the keyword `debugger`, to stop the execution at that point in the browser.

Let’s say, we add a breakpoint when `thunderbolt()` was called.

![The **debugger** stops the execution at the custom breakpoint, and the function **call-stack** at that point can be viewed on the right side.](https://cdn-images-1.medium.com/max/4084/1*7ajrjhWdWgzo3xfRA2yBLA.png)The **debugger** stops the execution at the custom breakpoint, and the function **call-stack** at that point can be viewed on the right side.

In the image above, we can see that the execution was stopped at the point where we mentioned the `debugger` keyword, as soon as `thunderbolt()` is called. At this point, we will not observe any execution of code that comes after the `debugger` (just the `thunderbolt()` log, in this case).

Our primary point of interest right now, is the **call-stack** which is clearly illustrated on the right-hand side, same as we determined in the example above. `(anonymous)` at the bottom of the stack, refers to the initial global call to `choosePikachu()`.

## **Binding rules for “this”**

Now that we understand what a **call-site** and a **call-stack** is, we can learn about how a **call-site** determines what this will hold during execution.

There are **four general rules** which apply. First, let’s understand them *independently*, and then, their *order of precedence* when multiple rules can apply to the **call-site**.

## **1. Default Binding**

This is the default catch-all rule, when none others apply. It comes from the most common case of a function invocation, which a standalone function call.

Let’s look at the below example.

{% gist https://gist.github.com/AnimeshPandey/357caa47504bf92ddfdcf83d6c277508 %}

The variable `ultraBall` declared in `global` scope is the same as declaring a property on the `global` object of the same name.

Inside `getPokemon()`, the reference to this defaults to the `global` object. Hence, we would see the value of `this.ultraBall` getting logged.

However, if `strict` mode is in effect globally or inside `getPokemon`, the `global` object is not permitted default binding. In that case, we will see the error `TypeError : 'this' is 'undefined'`.

## **2. Implicit Binding**

If the call-site has a context object (if a function is called through an owning or containing object, as its property), implicit binding applies.

The rule states that, when there is a context object for a function reference, it’s *that* object that should be used for its method calls’ `this` binding.

Let’s look at a few examples to illustrate the different cases which can arise.

{% gist https://gist.github.com/AnimeshPandey/635a3ba11e528944e2bac871698f03c3 %}

Since the object `pikachu` is the `this` for the `getBaseSpeed` call, `this.baseSpeed` is synonymous to `pikachu.baseSpeed`.

Let’s look at another example to see how only the top or last level of an Object property reference chain matters to the call-site for implicit `this` binding.

{% gist https://gist.github.com/AnimeshPandey/afea3750e219b98bea75fd3e5bad97f3 %}

As we can see, the `baseSpeed` value is still `90`. That’s because the call to `getBaseSpeed` is bound to its direct caller, `pikachu`, which serves as its `this` binding. In this context, the `baseSpeedvalue` is `90`.

Let’s look at a few more examples to show common cases where implicit binding can seem unexpected.

{% gist https://gist.github.com/AnimeshPandey/8045aaa02c0f2e2dccfd18d9c5402dad %}

In this example, we have lost our implicit `this` binding to `pikachu` in case of assigning `pikachu.getBaseSpeed` to a different variable `baseSpeedFunction`. Now, for `baseSpeedFunction`, `this` refers to the `global` object (*default binding* takes place). Hence, for the call, `this.baseSpeed` will be `50`.

Now, a more common and not-so-obvious way this loss of implicit binding can occur is when we pass a callback function. Consider the following example :

{% gist https://gist.github.com/AnimeshPandey/142d2ccf62739f92ec052ec42edb048e %}

Once again, inside the callback function executor `executeFunction`, we are effectively passing a reference to `pikachu.getBaseSpeedfunction`. Upon execution, `this` will be bound to the `global` object again (or throw a `TypeError`, if `strict` mode is enabled), instead of `pikachu`.

It’s quite common for function callbacks to lose their `this` binding. Another unexpected outcome can arise when the function we’ve passed our callback to, intentionally alters the `this` for the call. For example, *Event handlers* in popular JavaScript libraries often modify `this` to point to the `DOM element` that triggered the event.

You are not really in control of how your callback function reference will be executed. So far, you don’t have any way of controlling the call-site to assign the binding you intended. This is where ***explicit binding*** comes into play.

## **3. Explicit Binding**

To resolve the unintended loss of `this` with implicit binding, we can explicitly set the value of `this` to a given object for a function call.

There are several in-built methods that can help us achieve **explicit binding**, like :

### The bind() method

`bind()` is a method of the `Function.prototype` property. This means `bind()` can be used by every single function.

The `bind()` method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

In other words, `bind()` returns a new function that is hardcoded to call the original function with the `this` context set as specified.

{% gist https://gist.github.com/AnimeshPandey/e0bfb152122beef15d0d98cb179e270a %}

### The call() and apply() methods

`call()` and `apply()` are also methods of the `Function.prototype` property, with similar but slightly different usage.

The `call()` method calls a function with a given `this` value and arguments provided individually.

Whereas, the `apply()` method calls a function with a given `this` value, and arguments provided as an array (or an [array-like object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#working_with_array-like_objects)).

{% gist https://gist.github.com/AnimeshPandey/def3e56168a4d26797153e5b1c0ba62b %}

Invoking `Pokémon` with explicit binding by `Pokémon.call()` or `Pokémon.apply()` allows us to force its `this` to be the `this` of function `PokémonExtension`.

Also, a noteworthy aspect of the above example is that all instances of `PokémonExtension` will bind their respective `this` to the execution of `Pokémon` within them. Such an explicit binding is also called **hard binding.**

## **4. new Binding**

In JavaScript, there is really no such thing as “constructor functions”, but rather construction call of functions.

When a function is invoked with `new` in front of it, otherwise known as a constructor call, the following things are done automatically.

1. A brand new object is created (aka constructed) out of thin air.

1. The newly constructed object is `[[Prototype]]`-linked. (Out of the scope of this article)

1. The newly constructed object is set as the this binding for that function call.

1. Unless the function returns its own alternate object, the new invoked function call will *automatically* return the newly constructed object.

{% gist https://gist.github.com/AnimeshPandey/cc8d8ef4bff6298260e589c6f428eeb3 %}

## **All binding rules in action**

It should be clear that the *default binding* is the lowest priority rule of the four.

Let’s compare *implicit binding, explicit binding,* and *new* binding with each other.

### Implicit versus Explicit

{% gist https://gist.github.com/AnimeshPandey/2eeb59b3e16ca186cc61bf80d2b3f725 %}

As we saw, the *explicit binding* of `firstAttempt.catchPokémon` with `secondAttempt` took precedence over its own *implicit binding*, as it did for the second case as well.

Hence, *explicit binding* is of higher precedence than *implicit binding*.

### Implicit versus new

{% gist https://gist.github.com/AnimeshPandey/d360a84e633b13e6fdbbe8dba0bcec01 %}

So, *new binding* is more precedent than *implicit binding*.

### Explicit versus new?

`new` and `call` or `apply` cannot be used together, so something like `var fourthAttempt = new catchPokémon.call(firstAttempt);` is not allowed to test *new binding* directly against *explicit binding*. But, we can still use a *hard binding* to test the precedence of the two.

{% gist https://gist.github.com/AnimeshPandey/e793ab4dadf80404d014781634a4e02a %}

`attemptBinder` is hard-bound against `firstAttempt`, but `new attemptBinder(“Steelix”)` did not change `firstAttempt.name` to `"Steelix"`, as we may have expected, but it remained `"Onix"`.

Instead, the hard-bound call to `attemptBinder("Steelix")` is able to be overridden with `new` . Since `new` was applied, we got the newly created object back, which we named `secondAttempt`, and we see that `secondAttempt.name` indeed has the value `"Steelix"`.

Thus, the newly created this is used, rather than the previously specified *hard-binding* for this. Effectively, `new` is able to override *hard-binding*.

The primary reason for this behaviour is to create a function that essentially ignores the this *hard-binding*, and presets some or all of the function’s arguments.

## **Finally, determining “this”**

We can summarize the rules for determining this from a function call’s **call-site**, in their order of precedence.

Here they are :

1. Is the function called with `new` ? If so, this is the newly constructed object *(New binding).* Example, `var attempt = new catchPokémon("Pidgey");`

1. Is the function called with `call` or `apply` , even hidden inside a `bind` *hard-binding*? If so, this is the explicitly specified object (*Explicit binding)*. Example, `var attempt = catchPokémon.call("Pidgeotto");`

1. Is the function called with a context, otherwise known as an owning or containing object? If so, `this` is that context object (*Implicit binding)*. Example, `var attempt = firstAttempt.catchPokémon("Pidgeot");`

1. Otherwise, this defaults to the `global` object, or `undefined` in `strict` mode (*Default binding).*

## **Summary**

Determining the this binding for an executing function requires finding the direct **call-site** of that function.

Once examined, four rules can be applied to the call site, in this order of precedence.

1. Called with `new`? Use the newly constructed object.

1. Called with `call` or `apply` or `bind`? Use the specified object.

1. Called with a context object owning the call? Use that context object.

1. Default : `undefined` in `strict` mode, `global` object otherwise.

## **Credits**

1. Official documentation: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)

1. You Don’t Know JS: this and Object Prototypes, by Kyle Simpson.

### Thanks for reading! ❤️
<a href="https://www.buymeacoffee.com/anmshpndy" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-red.png" align="center" width="250" height="150" alt="Buy Me A Coffee"></a>