bind() - call() - apply()
In other object-oriented programming languages, the this keyword always refers to the current instance of the class.
Whereas in JavaScript, the value of this depends on how a function is called.
Example:
const person = {
firstName: 'John',
lastName: 'Doe',
printName: function() {
console.log(this.firstName + ' ' + this.lastName);
}
};
If we call person.printName(); then it will give o/p as John Doe
Here, I am calling the printName() method using the person object, so the this keyword inside the method refers to the person object.
Let's try below one:
const printFullName = person.printName;
printFullName();
Surprisingly, this prints: undefined undefined
Here, we are storing a reference of person.printName to printFullName variable. After that, we are calling it without an object reference, so this will now refer to the window (global) object or undefined (in strict mode). If the script is in strict mode, this refers to undefined, so console.log() will return an error.
So, sometimes we accidentally lose reference to the this variable. So how can we prevent that from happening?
We use call, bind and apply methods to set the this keyword independent of how the function is called. This is especially useful for the callbacks.
bind()
The bind method creates a new function and sets the this keyword to the specified object.
const john = {
name: 'John'
};
const jane = {
name: 'Jane'
};
function greeting(lang) {
console.log(`I am ${this.name}`);
}
const greetingJohn = greeting.bind(john);
greetingJohn();
const greetingJane = greeting.bind(jane);
greetingJane();
We can use the bind method on the greeting function to bind the this keyword to john and jane objects.
call()
The call method sets the this inside the function and immediately executes that function.
function greeting() {
console.log(`Hi, I am ${this.name} and I am ${this.age} years old`);
}
const john = {
name: 'John',
age: 24,
};
const jane = {
name: 'Jane',
age: 22,
};
// Hi, I am John and I am 24 years old
greeting.call(john);
// Hi, I am Jane and I am 22 years old
greeting.call(jane);
The difference between call() and bind() is that the call() sets the this keyword and executes the function immediately and it does not create a new copy of the function, while the bind() creates a copy of that function and sets the this keyword.
apply()
The apply() method is similar to call(). The difference is that the apply() method accepts an array of arguments instead of comma separated values.
function greet(greeting, lang) {
console.log(lang);
console.log(`${greeting}, I am ${this.name} and I am ${this.age} years old`);
}
const john = {
name: 'John',
age: 24,
};
const jane = {
name: 'Jane',
age: 22,
};
// Hi, I am John and I am 24 years old
greet.apply(john, ['Hi', 'en']);
// Hi, I am Jane and I am 22 years old
greet.apply(jane, ['Hola', 'es']);