The this
keyword has got to be one of the most misunderstood concepts in Javascript, especially to beginners. I remember being frustrated by it on more than one occasion. Some might even say that it is one of the most challenging concepts to understand in Javascript. In order to read and write good Javascript code, you must understand the this
keyword. In this tutorial, I will endeavor to break it down and show you how the this
keyword works and that there is no reason to be scared of it.
What is the this keyword?
The this
keyword is a special variable automatically created for every function by Javascript, and it will point to or take the value of the "owner" of the function that is calling it. The this
keyword is dynamic, and its value is assigned or known only when the function is called and depends on how the function is called.
There are four (4) ways to call a function in Javascript, and the value of the this
keyword changes in each way.
1) As a Method:
For a function to be called as a method, it must be defined as a property on an object or as a function that is attached to an object. When we call a method the this
keyword will point to the object on which the method is called, or it points to the object that is calling the method. Let's see an example below:
const student = {
name: 'Isaac',
class: 'Junior',
age: '16',
callStudent: function () {
return `${this.name} is ${this.age} years old`;
},
};
console.log(student.callStudent()); // Isaac is 16 years old
In the example above, the method is the callStudent
method because it is a function that is attached to the student
object. We then called the method and console logged it. Inside the method, we used the this
keyword, and we found the value of the this
keyword to be student
because it is the object that is calling the callStudent
method. And that’s why this.name
is Isaac because it means student.name
and this.age
is 16 because it means student.age
.
2) Calling functions as regular functions:
This is probably the default way of calling function. The this
keyword can have different values when used in a regular function call depending on whether you are coding in strict mode or default mode (non-strict mode).
- In strict mode: Strict mode doesn't allow for default binding and therefore when used in strict mode, the
this
keyword in a regular function call isundefined
'use strict';
function myFunction() {
console.log(this === undefined); // true
}
myFunction();
- In default mode: When used in default mode, the
this
keyword refers to the global object, which in the case of the browser is thewindow
object. Let us see an example below:
function printThis() {
console.log(this)
}
printThis()
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
Note: It should be noted that using this
in default mode can be very problematic and can introduce bugs into your code because you aren’t sure where your this
keyword is pointing. Therefore it is advised that you always write your Javascript code in strict mode.
3) In a Constructor
A constructor is a function that creates an object and initializes that object with a class. A constructor is called when an object is declared with the new
keyword. The this
keyword is set to the newly created object. Let’s look at the example below:
function Sport(type) {
this.type = type;
}
Sport.prototype.getType = function () {
return this.type;
};
let sport = new Sport('Football');
console.log(sport.getType()); // Football
In the code block above, we created an object with the new
keyword, and then the this
keyword was set to the newly created object (Sport). That’s why we could access this.type
to get Football. The capital letter is used to show that the function is a constructor.
4) Using the call()
and apply()
method
All functions in Javascript are first class objects meaning that they have their own methods and properties. The call()
and apply()
methods are two of those methods. These methods lets you set the this
keyword when calling a function irrespective of whether that function is being called in the global scope or as the object's method, as we will see in the example below:
function getSport(prefix) {
console.log(prefix + this.type);
}
let footBall = {
type: 'Football!',
};
let cricket = {
type: 'Cricket!',
};
getSport(footBall, "It's called ") //[object Object]undefined
getSport(cricket, "It's called ") //[object Object]undefined
getSport.call(footBall, "It's called "); // It's called Football!
getSport.call(cricket, "It's called "); // It's called Cricket!
getSport.apply(footBall, ["It's called "]); // It's called Football!
getSport.apply(cricket, ["It's called "]); // It's called Cricket!
In the example above, we see that when we called the getSport
function that it returned [object Object]undefined
because there is no connection between getSport
, footBall
, or cricket
. Therefore, the this
keyword will result in undefined
in strict mode or to the global object in default mode. However, when we use call()
and apply()
, we invoke the this
keyword of footBall
and cricket
on the getSport
function.
Note: The difference between apply()
and call()
method is that apply()
takes in arguments as an array while call()
requires arguments to be passed in one by one.
Other ways in which the this keyword can be referenced
The this
keyword can also be referenced in other ways apart from when functions are called, and we are going to discuss them in this section.
Arrow functions
Arrow functions do not get their own this
keyword. Instead, if you use the this
keyword in an arrow function, it will simply be the this
keyword of the surrounding function (the parent function). Technically it is known as the lexical this
keyword because the arrow function inherits the this
keyword from the outer lexical scope (function).
const sayName = {
name: 'Isaac Junior',
regularFunction: function () {
console.log(this.name);
},
arrowFunction: () => {
console.log(this.name);
},
};
sayName.regularFunction(); // "Isaac Junior"
sayName.arrowFunction(); // undefined
In the example above, we created an object with two functions set as methods. When we called the first function which was a regular function, we notice that the this
keyword pointed to the object that was calling the method and that was why we got Isaac Junior in the console.
But when we called the second function which was an arrow function, we notice that we get undefined or nothing in the console and that is because arrow functions do not have their own this
binding.
Using the bind()
method
Sometimes, you might need to use a method over and over with the this
context of another object, and in that case, you could use the bind
method to create a brand new function with an explicitly bound this
. Let’s look at an example below:
let gender = {
type: 'male',
getType: function () {
return this.type;
},
};
let seaAnimal = {
type: 'Octupus',
};
let type = gender.getType.bind(seaAnimal);
console.log(type()); // Octupus
In the example above, we bound the this
keyword to the seaAnimal
object. And that's why the value of the type property is that of the seaAnimal
object in the console
Event Handlers
The this
keyword will always point to the DOM element that the handler function is attached to in event handlers. Let’s see an example below:
const words = document.getElementsByClassName('tags');
function turnBlue() {
this.style.backgroundColor = '#A5D9F3';
}
for (let i = 0; i < words.length; i++) {
words[i].addEventListener('click', turnBlue);
}
In the example above, we have an event listener that turns any class with tags
in our code blue when we click on it. We used the this
keyword, and as we can see, it points to the DOM element on which the event listener or handler is attached which in this case is words
.
Conclusion
In this article, we have looked at and broken down what the this
keyword is, and what it points to in every instance in which it is created. I hope that you will be more confident about making use of the this
keyword from now onwards whenever you are writing Javascript code.