DEV Community

Cover image for Do you really know JavaScript ? Part 2: Call, Apply And Bind
Kiran Raj R
Kiran Raj R

Posted on • Updated on

Do you really know JavaScript ? Part 2: Call, Apply And Bind

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);
Enter fullscreen mode Exit fullscreen mode
  1. thisVal represent the value this should be using when the function is invoked.
  2. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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]);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode
  1. thisVal is the value that will be set to the this keyword.
  2. 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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

when passing a method to the setTimeout function, this points towards the global object, here windows. In the global object there is no fnameor 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 :)

Do you really know JavaScript ? Part 1 : Undefined

Top comments (0)