this in JavaScript. The only article you need to read.
Tags: javascript, beginners, webdev, programming
Published: 2022-03-22 11:37:27


If you are like me, you have spent several hours trying to understand _**this**_. You have heard terms like, a function binds its own _**this**_, and you didn't get it. I have been there, that is why I am writing this article. The goal is to help you understand the concept in simple, clear terms.

This article is targeted at the following groups:
•	junior developers
•	senior developers

The following are the prerequisite knowledge required:
•	Functions in JavaScript
•	An understanding of the window object
•	Class syntax in JavaScript
•	Objects in JavaScript
•	Event listeners in JavaScript

This article does not cover advanced edge cases of the this keyword, please read the docs here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this.

The article is in two parts:

Part 1, discusses the everyday use of this:
•	what is this
•	this in regular functions

Part 2 covers the following:
•	this in arrow functions
•	this in special cases

What is `this `? `this` is a special keyword in JavaScript. _It always refers to an object, without exception_. So, we have solved the first part, this is a pointer in JavaScript. Onward, we go. The second part, _this is always declared in a function_. This is key to understanding `this`. For clarity, here are the rules again:

•	this is always a pointer to an object.
•	this is always defined inside a function.

Let's see a quick example:

```
let obj = {

country : 'nigeria',

getCountry(){
return this.country;
}
};

```


Don't worry about the code, it will be explained, just observe that `this` is in a function, and it refers to the object- `obj`.

Regular functions(for simplicity, will refer to any function other than arrow functions) and `this`. Read closely here. When `this `is defined in a regular function, it points to the object that invokes the function. In other words, it points to the object which called the function. This means that `this` in a regular function is NOT sure what to point to until the function is invoked. Consider the simple example above:

•	A function inside an object like this is called a method.

•	`this` in the `getCountry` function doesn't know what object to point to just yet, it's as confused as you and I.

•	the value of `this` becomes clear to JavaScript, when you invoke(run or call) the function.

•	the value of `this`, is set to the object that directly calls the function.

•	So, to call the `getCountry` method, we write:

```
obj.getCountry();
```

•	Guess what this refers to.

•	Yes, it refers to the `obj` object, as it was the object that called the function `getCountry.`

•	Hence, the output will be: nigeria.

Let's consider something more interesting. Given the following expressions, determine the output, and explain why. Try this yourself, before seeing my explanation.

```
First example:

function logger(str){
    return this.str;
}

logger(‘John’) // ??

```

```
Second example:

let obj = {
  name : 'John',

  getName(){
    
    function anotherFunc(){
      return this.name;
    }

    return anotherFunc();
  }
}

obj.getName() // ??

```

How did that go? It doesn't matter, so long you tried. Now, let's consider the first example:

•	When you call the function, `logger`, what happens?

•	All JavaScript functions run within an object behind the scenes. This object is referred to as the _**context of the function**_.

•	_**A little trick, to determine the context of a function is to look to the left of the function when it is invoked.**_

•	`this `always refers to the context.

•	To call the `logger` function, we write `logger();`

•	In reality, this is is what is happening : `window.logger();`

•	This is because the `window `object is the closest object to the function, hence it is its context.

•	The function logs `undefined`, as the `str` property doesn't exist on the window object.

•	If we remove the `str `parameter from the function, and just return `this`, you get the `window `object.

In this second example, to access the `getName` method, we write `obj.getName()`,but we get `undefined` as our result. This happens because our method returns another function. A function nested inside of the `getName` method- a nested function. The nested function is the one with `this`.
What does `this` point to? Well, let's try to call the nested function and then look left.
	
```
obj.getName.anotherFunc()
```

As you can see, the closest caller of the `anotherFunc` function is not an object but a method: `getName`. But `this` doesn't point to a function, ever. What is really happening?
Well, this is it:
	
```
obj.getName.window.anotherfunc
```

Hence the object closest to `anotherFunc` is the window.
This object doesn't have a name property on it, so it returns `undefined`.

This logic is true for all regular functions nested in a method, no matter how deep the nesting, the context is always the window object. You can try this out yourself.

We have discussed some key concepts thus far, I advise you to practice some questions at this point to test your understanding.
Try these two(answers are immediately after both questions):

```
Question 1:

const object = {
  message: 'Hello, World!',
  getMessage() {
    const message = 'Hello, Earth!';
    return this.message;
  }
};
console.log(object.getMessage()); // What is logged?
```

```
Question 2:

const object = {
  message: 'Hello, World!'
};

function logMessage() {
  console.log(this.message); // 
}

logMessage();  // ??

```
These questions are gotten from Dmitri Pavlutin, you can check out his blog here for more : https://dmitripavlutin.com/javascript-this-interview-questions/

Answer to question 1:

`Hello, World!`

Answer to question 2:

`undefined`

The concepts that we have discussed so far are the natural ways this works. This is what is called _implicit binding_ of this. But sometimes, we want to force `this` to behave in a more flexible manner. For example, in the `anotherFunc` above, say we want `this` to point `obj`, rather than the `window` object. Well, we must _explicitly_ tell JavaScript to do that.

Explicit this binding can be achieved in one of three simple ways:

•	`call`(context, arg)
•	`apply`(context, [arg])
•	`bind`(context, arg)

The call method is applied to a function to change the context of the function i.e to change what `this` is points to. We can change it to whatever we like.

To change `anotherFunc` to reference our `obj `object, we reframe our object like this:

```
let obj = {
  name : 'John',
  getName(){
    
    function anotherFunc(){
      return this.name;
    }
    return anotherFunc.call(obj);
  }
}

obj.getName() // "John"
```

The second parameter of the call method is `args `, which refers to the argument you want to pass into the function. Here is an example:

```
function welcome(event){
  return 'Hello ' + this.name + ' welcome to the ' + event
}

let obj = {
  name : 'John'
}

welcome.call(obj,'Oscars'); //

'Hello John welcome to the Oscars'

```

The apply method works exactly like the call method ,except it takes `args` in the form of an array. For example:

```
function welcome(a, b, c){
  console.log('Hello ' + this.name + ' welcome to the ' + a);
  console.log('Hello ' + this.name + ' welcome to the ' + b);
  console.log('Hello ' + this.name + ' welcome to the ' + c);
}

let obj = {
  name : 'John'
}

let events = ['Grammy', 'Oscars', 'World cup'];

welcome.apply(obj, events);

// Hello John welcome to the Grammy
// Hello John welcome to the Oscars
// Hello John welcome to the World cup


//a, b, and c ---> the indices of the events elements.
```

The bind method works like the call method, however it returns a new function that can be called later. For example:

```
function welcome(event){
  return 'Hello ' + this.name + ' welcome to the ' + event
}

let obj = {
  name : 'John'
}

let bindFunc = welcome.bind(obj,'Oscars'); 

bindFunc(); //


'Hello John welcome to the Oscars'
```

I hope this article, has clarified this for you. Part 2 will go into some quirky parts of `this`, for now, cheers and see you soon.