Call, apply and bind methods are used to set the this
value, independent of how the function is called. We can use the method of an object with another object, without worrying about where the this
keyword will be pointing.
Call Method
The call
method help us to call a method of a object from another object and it sets value for the this
keyword if we provide one, the function is executed immediately. Call method takes parameters for the function as comma separated values.
functionName.call(thisVal, arg1....argN);
-
thisVal
represent the valuethis
should be using when the function is invoked. -
arg1....argN
represents the list of argument that will be passed to the function as parameters.
let obj1 = {
fname : "kiran",
lname : "raj",
display() { console.log(`${this.fname} ${this.lname}`) }
};
obj1.display(); // kiran raj
In the above code obj1
has two properties(fname
, lname
) and one method (display
), the method simply console the fname
and lname
properties of the object which is pointed by the this
keyword. When we invoke the method by calling obj1.display()
, we get a console output "kiran raj", here the this
keyword inside the method points towards the object before the dot that cause the invocation, here obj1 is before the dot and this
will point towards obj1. So this.fname
become kiran
and this.lname
become raj
. This is how JavaScript normally works.
Let's try to access the display method from another object.
let obj1 = {
fname : "kiran",
lname : "raj",
display() { console.log(`${this.fname} ${this.lname}`)}
}
let obj2 = { fname : "Vishnu", lname : "R",}
obj2.display()
//Uncaught TypeError: obj2.display is not a function
I tried to call display method with obj2
but I got an error, so there is no ways to call display from another object?
There are certain ways, lets me show one of those ways, using call method.
let obj1 = {
fname : "kiran",
lname : "raj",
display() { console.log(`${this.fname} ${this.lname}`)}
}
let obj2 = { fname : "Vishnu", lname : "R",}
obj1.display.call(obj2); //Vishnu R
Yay, we were able to call the display method from another object, the surprise is not ending there, look at the result, it prints the properties of obj2
not obj1
. what it means? It means that this
keyword is now pointing towards obj2.
So we can say that call method help us to invoke a method belonging to an object using another object. Call method also provide a new value to this
of the method. Call method accept arguments that can be passed as parameters to the method as comma separated values.
Lets look at another example
let obj1 = {
count : 0,
increaseCount() {
this.count++;
console.log(this.count);
}
}
let obj2 = { count:100 };
obj1.increaseCount(); // 1
obj1.increaseCount(); // 2
obj1.increaseCount.call(obj2); // 101
obj1.increaseCount.call(obj2); // 102
Finally one more example, try it and find the output.
function Car(type, company, yr){
this.yr = yr;
this.company = company;
this.type = type;
}
function Sedan(type, company, yr){
Car.call(this, type, company, yr);
this.sedan = true;
}
function printDetails(){
console.log(`${this.type}`);
console.log(`${this.company}`);
console.log(`${this.yr}`);
if(this.sedan){console.log("Sedan");}
}
let myCar = new Sedan('Petrol', 'Hyundai', 2019);
printDetails.call(myCar);
Apply Method
Apply
method is same as call
method the only difference is, apply method accept parameters for the function to which it is attached as argument array.
functionName.apply(thisVal, [argArray]);
Let's look at an example
let obj1 = {
fn : "kiran",
ln : "raj",
display(fn, ln) {console.log(`${this.fn} ${this.ln}`)}
}
let obj2 = {fn : "Vishnu",ln : "R",}
obj1.display.apply(obj2); //Vishnu R
let obj3 = {
fn: "arun",
ln: "v.i.",
getDetails(age, place){
console.log(`${this.fn} ${this.ln}`);
console.log(`${age} : ${place}`);
}
};
obj3.getDetails.apply(obj1, [33, 'venjaramoodu']);
// kiran raj 33 : venjaramoodu
obj3.getDetails.apply(obj2, [33, 'venjaramoodu']);
// Vishnu R 33 : venjaramoodu
Compare the code with that of the call
method, the only difference you will find will be the argArray
, which contains all the parameters for the function to which the apply
method is attached.
One more example
function Car(type, company, yr){
this.yr = yr;
this.company = company;
this.type = type;
}
function Sedan([type, company, yr]){
Car.apply(this, [type, company, yr]);
this.sedan = true;
}
function printDetails(){
console.log(`${this.type}`);
console.log(`${this.company}`);
console.log(`${this.yr}`);
if(this.sedan){
console.log("Sedan");
}
}
let myCar = new Sedan(['Petrol', 'Hyundai', 2019]);
printDetails.call(myCar);
Let me summarize, Apply method is used to call a method/function of an object with another object, apply
method can assign a user assigned value to this
keyword, the function is immediately invoked.
Bind Method
"The bind() function creates a new bound function, which is an exotic function object that wraps the original function object. Calling the bound function generally results in the execution of its wrapped function." : MDN Docs
Unlike call or apply function bind function creates a new function, a bound function.
let boundFuntion = functionName.bind(thisVal, arg1.....argN)
-
thisVal
is the value that will be set to thethis
keyword. - arg1......argN argument values for the original function.
let obj3 = {
fname : "kiran",
lname : "raj",
display(title) {
console.log(`${title}.${this.fname} ${this.lname}`)
}
}
obj3.display("Mr"); // Mr.kiran raj
I will try to explain the above code snippet, we create an object, obj3, which have two properties "fname" and "lname" and a method display. The display method simply logs to the console fname and lname of this
, with a title which it get as parameter. We invoke the method,obj3.display("Mr");
and got a output "Mr.kiran raj" as the fname
and lname
value of this
is "kiran" and "raj" respectively.
Let's create another object which contain 'fname' and 'lname' as properties, can we call the display method from obj4?, Let's try
let obj3 = {
fname : "kiran",
lname : "raj",
display(title) {
console.log(${title}.${this.fname} ${this.lname})
}
}
let obj4 = {fname:"Vishnu", lname: "R"};
obj4.display("Mr");
// Uncaught TypeError: obj4.display is not a function
No we cannot call display from another object, if we do, it will throw an TypeError. Let's use bind method to call display from another object.
let obj3 = {
fname : "kiran",
lname : "raj",
display(title) {
console.log(`${title}.${this.fname} ${this.lname}`)
}
}
let obj4 = {fname:"Vishnu", lname: "R"};
let boundFn = obj3.display.bind(obj4);
boundFn("MR"); // MR.Vishnu R
let obj5 = {fname:"Arun", lname: "V.I."};
obj3.display.bind(obj5)("Mr"); // Mr.Arun V.I.
Yay, worked!, we create a bound function boundFn
, assign the value of obj3.display.bind(obj4)
to it, then invoke the bound function to get the result, "MR.Vishnu R". We can directly call without assigning the bound function to a variable, which is shown in the last line of the example.
Bind function is used to call a method/function of an object using another object, the bind function is not invoked immediately, bind function create a new bound function, which needed to be invoked to get the result.
Let's try one more example.
let myName = {
fn: "kiran",
ln: "raj",
printName(){console.log(`${this.fn} ${this.ln}`);}
}
setTimeout(myName.printName, 1000);
//undefined undefined
setTimeout(myName.printName.bind(myName), 1000);
//kiran raj
when passing a method to the setTimeout function, this points towards the global object, here windows. In the global object there is no fname
or lname
, so we get undefined, then we bind the this
to myName
and this points towards myName
and we get the output as "kiran raj".
Call, apply and bind help to access a method of object from another method and helps to assign new value to this
.
If the article have shortcomings or mistakes please point, your feedback is highly appreciated. Happy coding :)
Top comments (0)