Understand the keyword “this” in JavaScript

Written by lenafaure | Published 2017/05/07
Tech Story Tags: javascript | programming | front-end-development | frontend | tech

TLDRvia the TL;DR App

The "this" keyword in JavaScript can be confusing. Let’s demystify it !

In JavaScript, the this keyword has the same use as when we use it in a plain sentence : it refers to something that we already introduced earlier.

If I say : “I met Gary Vaynerchuck yesterday at a web convention. This guy is amazing.”, you immediately understand that “this guy” refers to Gary Vaynerchuck.

In a similar way, when used in JavaScript, this refers to an object, and more specifically to the object that invokes the code.

Consider this example:

Try it yourself

We created a customer object with properties and a greetCustomer method. The method uses the keyword this to refer to the customer object.

Note that this is able to access the properties of the object (firstName and lastName). It is because not only **this** refers to the **customer** object , but it also contains the value of the object : it can therefore access the methods and properties of the object.

When the greetCustomer method is invoked, this inside the method automatically refers to the object that invoked the method : the customer object . But before the method was called, and this is very important to grasp, _this_ was not assigned a value.

What does it mean ?

Take this function for example:

var sayCatName = function(catName){console.log("My cat's name is " + catName);};

What is it going to print ? Well, for the moment, not much, we have defined the function but we don’t know the value of catName until we invoke the function and pass it a cat's name :

sayCatName('Alphonse'); // Prints "My cat's name is Alphonse"

And that’s the exact same idea behind the this keyword : we won't know what it refers to until an object invokes a function where this is defined. In other words, the this keyword is not assigned a value until a function where it is defined is actually called.

So whenever you are trying to figure out what the **this** keyword refers to, ask yourself the question: "Where is this function invoked ?". Not where it is defined, but where it is called.

Whenever you are trying to figure out what the this keyword refers to, ask yourself the question: "Where is this function invoked ?". Not where it is defined, but where it is called.

This was a basic example, and there will be times when it will be more difficult to determine what this refers to in our code. Let's now dive into the four rules that will allow us to do so :

  • Implicit Binding (When this is inside of a declared object)
  • Explicit Binding (When we explicitly set the value of this using call, apply or bind)
  • The global context (When this is outside of a declared object)
  • The **new** keyword (When creating a new object)

1. Implicit Binding (When this is inside a declared object)

When the keyword this is found inside of a declared object, the value of this will always be the closest parent object.

Consider our customer object with a new method whatIsMyObject:

→ Try it yourself

We find the keyword this first Inside of the function greetCustomer. The closest parent object is the customerobject, which means that the value of the this is the customerobject.

When we print this alone inside the function whatIsMyObject, whose closest parent is also the customerobject, we get the whole object printed in the console, so we are now sure that the value of this is the customer object.

This is all well, but what happens when we have a nested object ?

A nested object

→ Try it yourself

We added a key to the customer object called address. The value of address is another object. Inside this object, we have an askAddress function that uses this to call the customer by his name.

However, this seems to be unable to access the property name of the customer object and prints "Dear undefined, please enter your address". Have you guessed why ?

Well let’s go back to our rule that says that the value of this will always be the closest parent object : here we are in the customer object, but also inside the nested address object, which is in fact the closest parent to this when it it inside the function askAdress.

Since the address object has no property firstName, this.firstName is undefined. We can also see that the whatIsMyObject function inside the address object doesn't refer to customer anymore but to address.

So how can we fix this ? What if we need our askAddress method to return the name of the customer ? We will need to explicitely change the value of this with the call, apply or bind methods.

2. Explicit Binding (When we explicitly set the value of this using call, apply or bind)

Functions in JavaScript are objects, and as objects they have several methods. We use the call, apply and bind methods of a function when we want full control over what the keyword this refers to.

Let’s take the code we used in the previous example:

Previoulsy, we were calling customer.address.askAddress, which was returning "Dear undefined…" , because the value of this inside the askAddress function refers to the address object, which does not have a firstNameproperty.

call()

By using the callmethod, we can change what we want the value of this to be : here we are going to change the value of this to be the customer object:

customer.address.askAddress.call(customer); // Prints "Dear John, please enter your address"

→ Try it yourself

It worked ! Note that we are not invoking askAddress , we just attach the method call onto it, so there are no parentheses after the askAddress method when we use call.

The parameter to the call method is what we want the keyword this to refer to, in this case the customer object.

apply()

The difference between call and apply can be seen when we have arguments to the function we want to use call or applyon.

We have created a new method calculateAge, which takes two arguments currentYear and birthDate.

Try it yourself

Both solutions are working, the only difference will be :

  • Using the call function, we pass arguments separated by a comma,
  • Using the apply function, we pass arguments as values in an array

bind()

bind works just like call, but instead of calling the function right away, it returns a function definition, with this set to the first parameter passed to bind().

→ Try it yourself

bind allows us to explicitly set this to the object we want. It generates a copy of the calculateAge function that we stored in the variable ageOfCustomer3, but it doesn't immediately call the function.

We can call the function later on in the code and pass it the arguments it needs to execute. It can be extremely useful to create functions with preset arguments that will be called later, with this already set to the right object.

3. The global context (When this is outside of a declared object)

this is in the global context when you find it "into the wild", outside of a declared object (meaning that there has not been an object defined which contains the keyword this).

In this case, its value refers to the global object, which, in the browser, corresponds to the window object.

And in fact, every variable declared in the global scope is actually attached to the window object :

→ Try it yourself

What if we find this inside a regular function call (not an object or an object's method) ? In that case, the this keyword also points at the global object.

→ Try it yourself

Here when I call the greetCustomer method, the nestedFunction will be invoked, and prints the global window object, even though we are inside the customer object. Why is that ?

What we have here is a regular function call inside a method, not a method of the object. Although it is written inside of the method, it is still a simple function.

4. The new keyword

One way of creating an object is by using the new keyword.

Consider this function Customer that defines an object:

function Customer(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;}

Inside of this function, we are defining the properties of the object with the keyword this, and they will be equal to the value passed to the function.

Hold on here, we are inside of a function; shouldn’t the value of this be the global object, as we saw earlier ?

But in this case, we are not going to make a regular function call to create a new object. Instead, we are going to use the new keyword, and the rule is that the value of this changes when you use the new keyword.

var customer1 = new Customer("John", "Smith");

console.log(customer1.firstName + " " + customer1.lastName); // Prints "John Smith"

→ Try it yourself

this now refers to the object that is created when the new keyword is used. We are storing that object in a variable called customer1 , that can now access the firstName and lastName properties.

Conclusion

To know what is the value of this inside of your code, always ask yourself the question:

Where is the function invoked ?

There are some very tricky parts to this that are reviewed in great detail in this article :

“The this keyword is most misunderstood when we borrow a method that uses this, when we assign a method that uses this to a variable, when a function that uses this is passed as a callback function, and when thisis used inside a closure - an inner function.”

You will surely often encounter some real-world problems while using native JavaScript or libraries like jQuery, and an understanding of the basic workings of this will be of great help in those cases.

Want to learn more ? Check out my other articles on the basics of JavaScript:

I hope you enjoyed this introduction to the JavaScript keyword “this”.

Feel free to comment and like this article so that others can find it easily on Medium !


Published by HackerNoon on 2017/05/07