Introduction
One of the most discussed and confused topics among JavaScript developers.
Let's understand this
in JavaScript in-depth.
Before getting started with this, we need to understand a little about the JavaScript runtime environment and how JavaScript code is executed.
Execution Context
The environment (or scope) in which the line is being executed is known as the execution context. The JavaScript runtime maintains a stack of these execution contexts, the top execution context is the one currently being executed.
The object this refers to changes every time the execution context is changed.
Default case:
this
refers to the global object (aka window object in browser)
By default, the execution context is global — it means if a code is being executed as part of a simple function call, then this refers to a global object.
Example:
function bar () {
console.log("Let's understand this in JavaScript");
console.log(this === window);
}
bar(); //prints Let's understand this in JavaScript
console.log(this === window) //Prints true on console.
In strict mode, then the value of this will be marked as undefined. The global object refers to undefined in place of the windows object.
function baz () {
'use strict';
console.log("Let's understand this in JavaScript");
console.log(this === window);
}
baz() // Strict mode enabled, prints false
//prints Let's understand this in JavaScript
this
points to a new instance
When a function is invoked with the new keyword, the function is known as a constructor function and returns an instance/object.
In such cases, the value of this refers to a newly created instance.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.printName = function() {
console.log(`Your name is : ${this.firstName} ${this.lastName}`);
}
}
const p1= new Person("Jane", "Dane"); // created an instance as new operator is used
p1.printName(); // Prints "Your name is : Jane Dane"
const p2 = new Person("John", "Doe");
p2.printName(); // Prints "Your name is : John Doe"
Since we used the new operator here, the function Person is now a constructor function and return a new instance.
this now points to a new instance of Person with properties firstName as Jane and lastName as Dane.
In case of p2.printName(), this points to a complete new instance of Person with properties firstName as John and lastname as Doe.
this
with the fat-arrow function
In ES6, fat-arrow functions were introduced
this in fat-arrow points to the same object where it’s referring to outside of the function.
function add(num1, num2, callback) {
callback(num1*num2);
}
const person = {
num1: 50,
num2:20,
makeAddtition: function() {
add(this.num1, this.num2, function(sum) {
console.log(sum);
console.log(this === window);
})
}
}
person.makeAddtition();
//Prints 70
//Prints true
The callback function is invoked as a simple function call inside the add function, this here refers to the global object inside the execution context of the callback method.
this
refers to an invoker object
In JavaScript, the property of an object can be a method or a simple value. When an object’s method is invoked, then this refers to the object which contains the method being invoked.
const person = {
username: "John",
printName:function(){
console.log(this.username)
}
}
person.printName() //Prints "John", this points to person object and username is set to John
const printName2 = person.printName
printName2() //Prints "undefined", this now points global/window object and global object has no
//username property
var username="Robert Paul"
printName3() //Prints Robert Paul", this points to global object and global object has username
//property
this
with call, apply and bind
Every function in JavaScript has call, bind, and apply methods. These methods can be used to set a custom value to this in the execution context of the function.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.printName = function() {
console.log(`Your name is : ${this.firstName} ${this.lastName}`);
}
}
const person = new Person("John", "Doe");
person.printName(); // Prints "Your name is : John Doe"
const personTwo= new Person("Jane", "Dane")
person.printName.call(personTwo); // Here we are setting value of *this* to be personTwo object
//Prints "Your name is : John Doe"
The difference between the call and apply methods is the way an argument is passed. In case of apply, the second argument is an array of arguments, whereas in the case of the call method, the arguments are passed individually.
Bind also works the same, the only difference is instead of calling the function, bind returns a new function that is associated with the passed context.
Summary
By default, this refers to the global object, window object in the case of a browser When a function is called using the call and apply methods, this refers to the value passed as the first argument of the call or apply method When a method is called as a property of an object, this refers to the object When a function is called with the new operator, this refers to the newly created instance
If you find this blog useful, do consider commenting/liking the post.