call
, apply
and bind
methods are used to explicitly bind this
object to a function. this
keyword refers to an object which is executing the current code. These three methods are very useful to bind this
to methods when you don't know how your function will be called or you don't have control on the excution context in which your method will be call.
Let's take a look at an example-
const hero = {
name: "Batman",
age:27,
printInfo: function(){
alert(`name: ${this.name}, age: ${this.age}`)
}
}
hero.printInfo(); // name:Batman, age: 27
In above example, we have a hero
object, and printInfo
method of hero
object is using this
keyword to print hero's information. executing hero.printInfo()
prints the correct user info by using this
keyword because printInfo
is executing in hero
object's context.
Now let say we want to print user info on user actions, for example on a button click. Let's assume that we have a HTML button.
// get the button
const button = document.getElementById("print-info-btn");
// add click event listener, and pass hero.printInfo
button.addEventListener("click", hero.printInfo);
On button click, hero.printInfo
function will be called and will not be able to print correct user information. Because on button click, the object which is executing hero.printInfo
method is button object, and the this
keyword inside hero.printInfo
method is also refering to the HTML Button elemnt.
In these kind of situation where you don't know in advance which object will execute your function once you passed it as callback to some other function, call
, apply
and bind
method are useful to bind this
keyword to whatever object you want to bind.
Every function in JavaScript have these three methods which allow us to specify the context in which the function will be invoked. Let's see them one by one.
bind
Method
bind
method binds this
keyword and returns a copy of a function which will have this
keyword set to provided value.
Let' see how can we solve our button click issue. Instead of passing hero.printInfo
to addEventListener
, we will explicitly bind this
to be equal to hero
object.
// get the button
const button = document.getElementById("print-info-btn");
const boundedMethod = hero.printInfo.bind(hero)
button.addEventListener("click", boundedMethod );
bind
method creates a new function, then it binds the this
keyword of newly method to provided object. bind
method also accepts zero or more arguments, which will be passed to bounded/actual method.
Let's modify printInfo
method to accept some arguments -
const hero = {
name: "Batman",
age:27,
printInfo: function(favouriteColor){
alert(`name: ${this.name}, age: ${this.age}, favourite color: ${favouriteColor}`)
}
}
bind
method's first argument is the context and after that you can pass multiple arguments one by one. In our case first parameter is the context and second paramter is favouriteColor
.
const boundedMethod = hero.printInfo.bind(hero, "black")
button.addEventListener("click", boundedMethod );
bind
method doesn't modify existing function, instead it creates and return a new function and bind thethis
keyword to provided value.
call
Method
call
method is exactly same as bind
except instead of creating a new function, call
method instantly executes the funtion with provide object as this
keyword.
const batman = {
name:"Bruce Wayne",
};
function sayHi(){
console.log(`Hi, I'm ${this.name} `)
}
sayHi(); // Hi, I'm undefined
In above example, We have sayHi
method which prints the name property of this
object. If we call sayHi
method without any context as we did in above example, the this
keyword in sayHi
will refer to global object. So how do we invoke sayHi
method such that the this
keyword inside sayHi
method refers to batman
object, we can't do batman.sayHi()
because batman
object doesn't have sayHi
method.
We can use call
method to invoke sayHi
method in context of batman
object.
sayHi.call(batman) // Hi, I'm Bruce Wayne
call
method's first argument is the context object and after the first argument you can pass multiple argument one by one. Let's modify sayHi
method to accept 3 additional arguments.
function sayHi(lang1, lang2, lang3){
console.log(`Hi, I'm ${this.name}, i can speak ${lang1}, ${lang2}and ${lang3} `)
}
We can pass lang1
, lang2
and lang3
parameter to sayHi
method like this -
sayHi.call(batman, "English", "Spanish", "French");
//Hi, I'm Bruce Wayne, i can speak English, Spanish and French
call
method doesn't modify existing function, nor does it creates a copy of function.
apply
Method
apply
method is exactly same as call
, but instead of passing multiple arguments one by one, apply
method accepts an array as its second argument and it will spread out array elements as arguments to the function.
instead of
sayHi.call(batman, "English", "Spanish", "French");
apply
accpets an array
const languages = [ "English", "Spanish", "French"];
sayHi.apply(batman, languages);
Conclusion
call
, apply
and bind
method are available on every function in JavaScript and they are used to explicitly bind this
keyword to given function. bind
method binds the this
and always creates and return a new copy of given function. Wheres call
and apply
methods instantly invoke the funtion with provide object as this
keyword.