The this keyword in JavaScript can be a nightmare in the beginning. But the thing is this keyword is not at all hard in JS, it's just act quit different then it acts in other programming language. With this blog, we will try to make this keyword very easy for you.
this keyword in different cases:
let obj1 = {
firstName: "John",
lastname: "Doe",
fullname: function(){
console.log(this.firstName + " " + this.lastname)
}
}
obj1.fullname()
Output:
John Doe
In the above example, we can see that the this keyword points to the obj1, when used in the method inside it.
function dance () {
console.log(`${this.name} is dancing ๐๐๐๐๐`)
}
var name = "John"
var obj1 = {
name: "Jinny",
dance : dance
}
var obj2 = {
name: "Jonny",
dance : dance
}
// Execution
dance()
obj1.dance()
obj2.dance()
output:
John is dancing ๐๐๐๐๐
Jinny is dancing ๐๐๐๐๐
Jonny is dancing ๐๐๐๐๐
In the above example we can see that the function dance is declared in the global context (in browser: window object).
When its called in the global context, it prints "John is dancing ๐๐๐๐๐", this means that this keyword in the case is point to the global object (window object) which has variable name = "John". So calling dance() is same as window.dance().
In obj1, obj2, we assign the dance property to the dance function. When we call obj1.dance() and obj2.dance(), the output is "Jinny is dancing ๐๐๐๐๐" and "Jonny is dancing ๐๐๐๐๐"
respectively.
From the above two example we can notice that "this keyword" points the object that has called it.
Remember, "this keyword" is lexically bond, rather its bond to the object calling it.
this keyword in the nested function inside the method:
let obj = {
firstName: "John",
lastname: "Doe",
hobbies: ["Reading Books", "Netflix and Chill ๐ฌ ๐ฌ"],
printHobbies: function(){
this.hobbies.forEach(function (hobby){
console.log(`${this.firstName} ${this.lastname} has hobby ${hobby}`)
})
}
}
obj.printHobbies()
output:
undefined undefined has hobby Reading Books
undefined undefined has hobby Netflix and Chill ๐ฌ ๐ฌ
The obj has property hobbies containing array and printHobbies, which is function in which we are looping the hobbies array in forEach by passing the callback function and print each hobby.
When we run the code, we get the result which is quit confusing, we get the firstName and lastName as undefined.
Well, there is no problem with the code, this is exactly how "this keyword" in javascript behaves.
As we confirmed in the above section that "this keyword" points the object that has called it.",
so keeping that thing in mind, lets analyze the code again. obj.printHobbies() calls the printHobbies() method in the obj object. So, "this keyword" should point to the obj object.
Now inside printHobbies method, the hobbies property of obj object is accessed with the help of this keyword. In the printHobbies we are using forEach which is calling the callback function,
so, in reality, the callback function is called by the printHobbies method and not the obj object, in this case "this keyword" won't point to the obj object. By default the this keyword points to the global object (window object). Thus we get undefined for the firstName and lastName in the callback function.
Now, how do we solve this issue ? Well there are multiple ways to get round this issues. Lets discuss few of them below:
Method 1: We use arrow function as callback function
let obj = {
firstName: "John",
lastname: "Doe",
hobbies: ["Reading Books", "Netflix and Chill ๐ฌ ๐ฌ"],
printHobbies: function(){
this.hobbies.forEach((hobby) => {
console.log(`${this.firstName} ${this.lastname} has hobby ${hobby}`)
})
}
}
obj.printHobbies()
John Doe has hobby Reading Books
John Doe has hobby Netflix and Chill ๐ฌ ๐ฌ
The arrow function works here because, arrow function lexically bonded to the scope. So, "this keyword" in arrow function will always point the object it is declared and not the object that calls it.
Method 2: Storing the object reference in a variable:
let obj = {
firstName: "John",
lastname: "Doe",
hobbies: ["Reading Books", "Netflix and Chill ๐ฌ ๐ฌ"],
printHoddies: function(){
var self = this
this.hobbies.forEach( function(hobby){
console.log(`${self.firstName} ${self.lastname} has hobby ${hobby}`)
})
}
}
obj.printHoddies()
output:
John Doe has hobby Reading Books
John Doe has hobby Netflix and Chill ๐ฌ ๐ฌ
Here, in the printHobbies method, we are storing the reference of this keyword (which at this moment is pointing the obj object) in self variable. Then we are using self instead of the this keyword in callback function.
There are many other ways in which you can tackle this issue, like using bind, or passing the this reference in the forEach as a parameter.
I hope you now have a clear picture about the "this keyword" is Javascript.