Understanding the this keyword in JavaScript
Tags: javascript, beginners, webdev
Published: 2023-02-27 01:37:33

The `this` keyword is a very important concept in JavaScript. However, it has always been a tricky topic to comprehend especially for new JavaScript developers as well as developers with experience in other programming languages. Although `this` is a bit of a complex topic, it is also one that appears as soon as you begin writing your first JavaScript programs. You will encounter it whether you are trying to access elements on the [DOM](https://dev.to/brandonbawe/introduction-to-dom-manipulation-5hjl), build classes in Object-oriented programming or use properties and methods of regular objects. In this article, we are going to take a deep dive into what the `this` keyword is all about. With this objective in mind, let's get right to it.

In JavaScript, `this` is a reference to an object. The object `this` refers to will vary depending on how and where `this` is being called. The object that `this` refers to varies implicitly based on whether it is global, on an object, or in a constructor, and can also vary explicitly based on usage of the `Function` prototype methods [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind), [call](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), and [apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply).

For the remainder of this article, our main focus will be to learn what `this` refers to implicitly based on context, and we’ll learn how to use the `bind`, `call`, and `apply` methods to explicitly determine the value of `this`. So let's go!

## Implicit Context
There are four main contexts in which the value of this can be implicitly inferred. These contexts are;

- the global context
- as a method within an object
- as a constructor on a function or class
- as a DOM event handler

### Global Context
If we call `this` by itself, meaning not within a function, object, or whatever, it will refer to the global window object. When you’re working in a browser, the global context will be `window` meanwhile if you’re working in Node.js, the global context is `global`. If you log the value of `this` in your browser console without any other code, you will see what object `this` refers to.

```javascript
console.log(this)
// Output
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
```
You can see that `this` is set to the `window` object which is the global object of a web browser.

You have probably learned that JavaScript functions have their own context for variables. You might be tempted to think that `this` will follow the same rules inside a function, but it doesn't. A top-level function will still retain the `this` reference of the global object. In the example below, we are going to log the value of `this` in a top-level function:

```javascript
function printThis() {
  console.log(this)
}

printThis()

//Output

Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
```
The example shows that even within a function, `this` still refers to the global object. However, this is not the case in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). When in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode), the value of `this` in the global context is `undefined`.

Generally, it is safer to use strict mode to reduce the chances of `this` having an unexpected scope. Someone will rarely want to refer to the `window` object when using `this`.

### As an object method
Methods are basically actions that can be performed on objects or tasks that an object can perform. A method uses `this` to refer to the properties of the object. Let's see what this looks like in code:

```javascript
const cameroon = {
  name: 'Cameroon',
  language: ['English', 'French'],

  describe() {
    console.log(`The official languages of ${this.name} are ${this.language[0]} and ${this.language[1]}.`)
  },
}

cameroon.describe()

//Output: 
"The official languages of Cameroon are English and French."
```
### A Class Constructor
A constructor on a class acts the same as a constructor on a function.

```javascript
class Country {
  constructor(name, yearofIndependence) {
    this.name = name
    this.yearofIndependence = yearofIndependence
  }

  describe() {
    console.log(`${this.name} gained independence in ${this.yearofIndependence}.`)
  }
}

const cameroon = new Country('Cameroon', 1960)

cameroon.describe()
```
`this` in the `describe` method refers to the instance of `Country`, which is `cameroon`.

### A DOM Event Handler
In the browser, there exist a special `this` context for event handlers. When using `this` in an event listener, it will refer to the DOM element that fired the event. In an event handler called by `addEventListener`, `this` will refer to `event.currentTarget`. More often than not, developers will simply use `event.target` or `event.currentTarget` as needed to access elements in the DOM, but since the this reference changes in this context, it is important to know.

In the following example, we’ll create a button, add text to it, and append it to the DOM. When we log the value of `this` within the event handler, it will print the target:

```javascript
const button = document.createElement('button')
button.textContent = 'Click me'
document.body.append(button)

button.addEventListener('click', function(event) {
  console.log(this)
})

//Output
<button>Click me</button>
```
## Explicit Context

To complicate matters a little more, javascript provides three native methods that can be used to manipulate the way the `this` keyword behaves. These methods are `call`, `apply` and `bind`. It is a little bit tricky to know exactly when to use any of these methods as it will depend on the context of your program. `bind` is particularly useful when you want to use events to access properties of one class within another class. Suppose you have separated your code into various parts that each perform their own specific actions, you can use `bind` to explicitly infer the object you want `this` to refer to. Now, its time for us to learn how to use these three native methods to explicitly determine the object `this` refers to.

### Call and Apply
With `call` we can invoke a method passing an owner object as an argument. In simpler terms, we can call a method indicating to which object the `this` keyword will refer to. Let's see an example to help us understand it better:
```javascript
const person1 = {
    firstName: 'Francesco',
    lastName: 'Sanchez',
    sayName: function() {
        return this.firstName + " " + this.lastName;
    }
}

const person2 = {
    firstName: 'Raul',
    lastName: 'Jimenez'
}

console.log(person1.sayName.call(person2));
//Output
"Raul Jimenez"
```
Here we have two objects. Each with its `firstName` and `lastName` properties, and then `person1` object has a `sayName` method.

Then we call the `person1` `sayName` method in the following way: `person1.sayName.call(person2)`.

By doing this, we're indicating that when the `sayName` method executes, the `this` keyword won't refer to the object that "owns" the method (`person1`) but to the object we passed as parameter (`person2`). As a result, we get the output we have seen above in our console.

> **Note**: If the given method accepts arguments, we can pass them as well when we invoke it with call as seen in the example below.

```javascript
const person1 = {
    firstName: 'Francesco',
    lastName: 'Sanchez',
    sayName: function(city, country) {
        return this.firstName + " " + this.lastName + ", " + city + ", " + country;
    }
}

const person2 = {
    firstName: 'Raul',
    lastName: 'Jimenez'
}

console.log(person1.sayName.call(person2, "Bogota", "Columbia"));
//Output
"Raul Jimenez, Bogota, Columbia"
```
The `apply` method works very similarly to `call`. The only difference between them is that `call` accepts parameters as a list separated by colons, and `apply` accepts them as an array.

So if we want to replicate the same example using `apply` we'd have to do it like this:

```javascript
const person1 = {
    firstName: 'Francesco',
    lastName: 'Sanchez',
    sayName: function(city, country) {
        return this.firstName + " " + this.lastName + ", " + city + ", " + country;
    }
}

const person2 = {
    firstName: 'Raul',
    lastName: 'Jimenez'
}

console.log(person1.sayName.apply(person2, ["Bogota", "Columbia"]));
```
### Bind
In the same way as `call` and `apply`, the `bind` method indicates the object to which the `this` keyword will refer when a given method executes.

But the difference with `bind` is that it will return a new function, without executing it. While with `call` and `apply` the function is executed right away, using `bind` we must execute it separately.

Let's see this in an example:

```javascript
const person1 = {
    firstName: 'Francesco',
    lastName: 'Sanchez',
    sayName: function() {
        return this.firstName + " " + this.lastName;
    }
}

const person2 = {
    firstName: 'Raul',
    lastName: 'Jimenez'
}
const sayPerson2Name = person1.sayName.bind(person2)

console.log(sayPerson2Name())

//Output
"Raul Jimenez"
```
### Arrow Functions
Arrow functions do not have their own this binding. Instead, they go up to the next level of execution. If you want to learn more about Arrow functions and how this behaves in Arrow functions, check out [this article](https://dev.to/brandonbawe/understanding-arrow-function-expressions-in-javascript-8mi).

## Conclusion
We have seen in detail how the `this` keyword works in JavaScript, how to implicitly and explicitly infer the object `this` refers to. I hope you enjoyed reading this article as much as I enjoyed writing it up. Hoping to bring more JavaScript packed articles to you soon. Stay blessed.