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:
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 :
this
is inside of a declared object)this
using call
, apply
or bind
)this
is outside of a declared object)**new**
keyword (When creating a new object)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
:
We find the keyword this
first Inside of the function greetCustomer
. The closest parent object is the customer
object, which means that the value of the this
is the customer
object.
When we print this
alone inside the function whatIsMyObject
, whose closest parent is also the customer
object, 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
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.
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 firstName
property.
call()
By using the call
method, 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"
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 apply
on.
We have created a new method calculateAge
, which takes two arguments currentYear
and birthDate
.
Both solutions are working, the only difference will be :
call
function, we pass arguments separated by a comma,apply
function, we pass arguments as values in an arraybind()
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()
.
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.
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 :
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.
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.
new
keywordOne 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"
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.
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 usesthis
, when we assign a method that usesthis
to a variable, when a function that usesthis
is passed as a callback function, and whenthis
is 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 !