JAW-DROPPING FUNDAMENTALS OF THE 'this' KEYWORD IN JAVASCRIPT.
Tags: javascript, webdev, tutorial, computerscience
Published: 2022-08-10 01:13:24

## Knowing the meaning, and practical applications of JavaScript's 'this' keyword.


JavaScript's `this` keyword is an incredibly powerful concept. It most times tends to cause confusion among beginners or developers who don't understand how to use it, as well as contribute to unwanted bugs in our code. In this article, we will investigate what the `this` keyword means, and three (3) magical methods which are essential for its application.

## Prerequisite
- Basic understanding of HTML and CSS.


- Basic understanding of JavaScript and how it works behind the scenes.

### What is the 'this' keyword?
The `this` keyword is a special variable created for every function's execution context.  
Behind the scenes in JavaScript, every function gets an execution context during execution. Each execution context comprises the variable environment, the scope chain, and **the `this` keyword.** 

You can think of the `this` keyword as a pronoun in English. Let's take an example, My name is Aahil, I love to write. The "I" in the sentence is referring to "Aahil". That is what the `this` keyword simply does, it refers to the function that is calling it.

The value of the created `this` keyword, points to the owner of the function in which it is being used. In other words, when a function is executed, it gets its own distinct `this` keyword, whose value is the function in which the  `this` keyword is used. 

Unlike other variables, the `this` keyword is not a **STATIC** variable. It gets its value depending on **HOW** the function is **CALLED**. Below are 3 ways by which functions are called in JavaScript 👇:

**(1) As a Method 👇:**

A function declared in an object is a method. The value of the `this` keyword when used in a method, points to the **object on which the method is called**.  

Let's take a code example.


```
const sample1 = {
  name: "Aahil",
  dateOfBirth: 1996,
  calcAge() {
    console.log(`${this.name} is ${2022 - this.dateOfBirth} years old`);
  },
};

sample1.calcAge();

``` 

Let's break down the code sample. The following activities occurred above;

- The object literal called `sample1` was created. It contains 2 properties, `name` and `dateOfBirth`, and a method called `calcAge()`.

- The `calcAge()` method prints to the console of the browser a string composed of the name property and a calculated date of birth.

- The sample1 object calls the `calcAge()` method.

**Output 👇:**

![This Keyword result1.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lx80emn3e8xvkpcr6oi1.JPG)

The value of the `this` keyword above is the object that calls the `calcAge()` method which is `sample1`. Therefore, `this.name` is the same as `sample1.name` which is the string 'Aahil'.

![This keyword image1.jpg](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9dxill0s7c3i9o3iksh.jpg)

We can go ahead and confirm the value of the `this` keyword. See the example below 👇

```
const sample1 = {
  calcAge() {
    console.log(this);
  },
};

sample1.calcAge();

``` 
**Output 👇:**

![This Keyword result2.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k537y8d8e35c675ui825.JPG)

As we can see above, the `this` keyword points to the object `sample1`.


**(2) As a normal function call 👇:**

When we create a function, it is expected that the function must be called before it runs. The value of the `this` keyword when used in a function returns as `undefined` when that function is called. This is true only for function expressions and function declarations but not arrow functions. 

**NOTE👉:** This only applies when you're in **strict mode**, otherwise, the `this` keyword points to the global window object.

Let's see this in action.

```
"use strict";

const sample2 = function () {
  console.log(this);
};

sample2();

``` 

In the code snippet above, we explicitly set the script to execute in strict mode. We also have a simple function expression `sample2()` which prints the `this` keyword to the browser's console. 

**Output👇:**

![This Keyword result3.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nzpk6jdngbg9wzj4wig4.JPG)

As earlier stated, the value of `this` here is returned as `undefined`  in strict mode. Now let's see the effect of having the same code run in **sloppy mode**.

```
const sample2 = function () {
  console.log(this);
};

sample2();

``` 
**Output👇:**

![This Keyword result4.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnu6ts7rp9gkfh35mray.JPG)

The output is the global window object - this is an object available in the global scope.

**NOTE👉:**
Using strict mode is very essential because it prevents JavaScript from failing silently and we set strict mode by adding the string '' use strict '' at the beginning of the script file.

We cannot talk about using `this` in function expressions and function declarations without mentioning its effect when used in  **ARROW FUNCTION.** 

**As an arrow function 👇:**

The arrow function is a simplified alternative for creating functions in JavaScript. Arrow functions don't get their own `this` variable, however, it uses the `this` keyword of its parent scope which is referred to as the lexical `this` keyword.

Let's take a code example.

```
const sample3a = () => console.log(this);

sample3a()

``` 

In the example above, the arrow function is logging the `this` keyword to the browser's console.

**Output👇:**

![This Keyword result5.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnu6ts7rp9gkfh35mray.JPG)

The result of running the code above returns the **global window object**. Remember, the value of the `this` keyword when a function is called in **sloppy mode** is the **global window object**. This means, the arrow function doesn't have its own `this` keyword, but it points to the `this` keyword of the **outer scope(parent scope).**

We can observe the `this` variable of the outer scope by just logging `this` to the browser's console without it being inside any code block(or function).


```
console.log(this)
``` 

**Output👇:**

![This Keyword result6.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnu6ts7rp9gkfh35mray.JPG)

The `this` variable of the outer scope is the global window object and that is why the `this` variable of the arrow function above is pointing to the global window object. The image below gives a summary of this.

![This keyword image2.jpg](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffmx3w89pkxl9ioexvtd.jpg)

We can see the value of the `this` keyword when the arrow function is put into another code block, in this case, another function.

```
const sample3b = function () {
  const sample3bArrowFunction = () => {
    console.log(this);
  };

  sample3bArrowFunction()
};

sample3b();

``` 

Let's break down the code snippet;

- A function `sample3b()` which holds an arrow function `sample3bArrowFunction()`. 

- `sample3bArrowFunction()` simply logs to the console, the `this` variable.

**Output👇:**

![This Keyword result6.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nzpk6jdngbg9wzj4wig4.JPG)

The result of this example is `undefined`. This is because the `sample3bArrowFunction()` doesn't get its own `this` variable, it uses the `this` keyword of the outer scope, which in this case is the function expression `sample3b()`.  

Remember from our background study, we established that function expressions return the value of `this` as `undefined`. Therefore, the `this` keyword of `sample3bArrowFunction()` will be `undefined` as well.

**NOTE👉:** The arrow function is **not a way of calling a function**, but it is an important and special case that we have to put into consideration when studying `this`.

**(3) As Event listeners 👇:**

When using event listeners in JavaScript, we select the element we want to listen to, then call the `addEventListener()` method with 2 parameters. The first parameter is the **event** we are listening for and the second parameter is the **function** that gets triggered when that event is triggered.

The `this` keyword inside the function that gets called when that event is triggered, points to the **element which triggers that event**. This is because in the document object model (DOM) all elements are objects, therefore, it would seem like an object was calling the function just like a normal method would. 

Let's discuss this further with an example.

```
const buttonEl = document.querySelector('.btn')
const handleClick = function(){
    console.log(this);
}
buttonEl.addEventListener('click', handleClick);

``` 

The following steps are carried out in the code snippet above;

(1) A variable `buttonEl` holds the button HTML element.

(2) A function `handleClick()` simply logs the `this` keyword to the browser's console.

(3) The `buttonEL` has an event listener attached to it, with 2 parameters. Which are;

- The `click` event, which listens for when the button is clicked.

- The `handleClick()` callback function, is called only when the button is clicked.

**Output👇:**

![This Keyword result7.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khrkv1ik7pen0rkplcuo.JPG)

The `this` keyword **points to the element calling the event,** and in this case, the element calling the event is the `button` element. This is why the output of our code snippet is the `button` element.

**NOTE 👉:**
 The value of the `this` keyword is only assigned when the function is **CALLED**.

We have established that the `this` keyword is not **STATIC**, which means it changes based on how a function is called. However, there are ways we can **manually** set the `this` keyword. How cool is that, let's get into it.

The following three(3) magical ✨ methods are used to **manually set** the `this` keyword;

(1)  The  **Call()** method 👇.

The `Call()` method allows a function/method defined in an object to be used by another object without rewriting that method.  By using the `call()` method, you can write a function once and then use it on multiple objects.

We make use of the `call()` method when we call a function. The `call()` method accepts a list of arguments, where the first argument is an object, this will be the **value of the `this` keyword**, and the rest are arguments pertaining to the function.

let's take a practical example.

```
function sample5() {
  console.log(`${this.name} is ${this.age} old`);
}

const sample5Obj = {
  name: "prince",
  age: 24,
};

sample5.call(sample5Obj);

``` 

The following actions occurred above;

-  A function `sample5()` simply prints to the console a name and an age. 
-  An object `sample5Obj` holds two(2) properties, name, and age. 

All this is nothing new at this point, until we call the function `sample5()` using the `call()` method, and we pass the object `sample5Obj` as an argument.

Let's see the result of this example.

**Output👇:**


![This Keyword result8.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pffqfe065izpjyps7lt5.JPG)

The output above takes the name and age variables from the `sample5Obj`. This implies that the value of the `this` keyword is pointing to `sample5Obj`. This happens because we used the `call()` method to set it **explicitly**. 

Remember that calling the function without using the `call()` method would have returned the value of `this` as `undefined`. Using the `call()` method, we can assign the function `sample5()` to multiple objects, we can see that below by adding another object.

```
function sample5() {
  console.log(`${this.name} is ${this.age} years old`);
}

const sample5Obj1 = {
  name: "Prince",
  age: 24,
};

const sample5Obj2 = {
  name: "Aahil",
  age: 45,
};

sample5.call(sample5Obj1);
sample5.call(sample5Obj2);

``` 

Here, we added another object `sample5Obj2` to show that the function can be used in multiple objects and the `this` keyword would **change** depending on what object we pass into the `call()` method.

**Output👇:**

![This Keyword result9.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ke97v7rbkoeds1841g9c.JPG)
 
The result of calling the function `sample5()` on both objects changes because we are changing the first argument of the `call()` method.

**NOTE👇:** 

The syntax for using the `call()` method is;

```
function.call(object, arg1, arg2,....,argn);

``` 
Where;

- The first argument defines what the `this` keyword will be

- The other arguments `arg1`, `arg2`, and `argn` defines the arguments of the function.


(2)  The **apply()** method👇.

The `apply()` method does the same thing as the `call()` method, the only difference is that you pass the arguments of the function as an array instead of passing them directly.

Let's take a code example.

```
function sample6(name, age) {
  console.log(this);
  console.log(
    `${name} is ${age} years old and the name of this object is ${this.objectName}`
  );
}

const sample6Obj = {
  objectName: "object1",
};


const args = ["aahil", 14];

sample6.apply(sample6Obj, args);

``` 

Let's break down the activities above;

(1) A function `sample6()` with parameters of name and age. `sample6()` logs to the browsers'  console the `this` keyword and a template string.

(2) An object `sample6Obj` which contains a property `objectName`.

(3) An array `args` which holds 2 items.

(4) `sample6()` is called using  `apply()`. This takes the `sample6Obj` as the first argument, signifying that the value of `this` would be `sample6Obj1`, and it takes the  `args` array as the second argument. 


**Output👇:**

![This Keyword result10.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w10ydbyf0e5qvabpd2j0.JPG)

Let's analyze our output now;

(1) The first output we have is the result of logging the `this` keyword to the browser's console. The output is the object `sample6Obj` which we set by using the `apply()` method.

(2) The second output is the template string made up of elements from the `args` array. Using apply allows us to pass our arguments into an array and pass the array as an argument when we call the function.

**NOTE:👉** `apply()` is not really in use now and the same pattern it uses can be done using the `call()` method and the spread operator. 

Let's see this below 👇.

```
sample6.call(sample6Obj, ...parameters);

``` 

**The output of this code will give you the same result as earlier.**


**NOTE:👇** 

The syntax for using the `apply()` method is;

```
function.apply(object, [args]);

``` 
The first argument defines what the value of `this` would be and the other argument defines the array of arguments pertaining to the function.


(3)  The **bind()** method 👇.

The `bind()` method is used to set the `this` keyword explicitly, just as the `call()` and `apply()` method. The only difference is that instead of calling the function immediately, it returns a new function with the `this` keyword bound to it. 

When we use the `bind()` method, we can get a brand new function with the value of `this` being whatever object we set it to. That function can now be used in multiple places.

**Example👇:**

```
function sample7(name, age) {
  console.log(this);
  console.log(
    `${name} is ${age} years old and the name of this object is ${this.objectName}`
  );
}

const sample7Obj = {
  objectName: "object1",
};

const sample7Bind = sample7.bind(sample7Obj);

sample7Bind("aahil", 24);

``` 

We have the same syntax as before and the only difference is the function `sample7Bind()`. This function is created when **the `bind()` method is used on the function  `sample7()` to explicitly set its `this` keyword to the object`sample7Obj`**. 

`sample7Bind()` is called with the arguments of the function with its `this` keyword pointing to the object `sample7Obj`.

**Output👇:**

![This Keyword result11.JPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tz52c22wto3x56f8a0r.JPG)

The output is the same as when we used `apply()` or `call()`, the only difference here is that the bind method **returns another function**, and the `apply()` and `call()` methods just **call the function directly.**

**NOTE 👉: ** A useful application of using `bind()` is **partial application**. This is when some arguments of a function are passed into the bind method as default, then on calling the function, that argument would be skipped as it now serves as a **default parameter** of that function.

## Conclusion

This is a very lengthy article, but I hope we achieved our goals for this article and we got a deeper understanding of how the `this` keyword **dynamically changes** based on how functions are **called** and how we can **explicitly** determine the value of the `this` keyword.

One key thing to note is that the `this` keyword is **simply a variable** and whenever you're not sure of what the `this` keyword is, you can** simply log in to the browser's console** to be on the safe side.

Thank you for reading 😊.