Call, Apply & Bind
In this blog post, I will quickly discuss the call(), apply() & bind() methods. These methods allows for dynamic change in the JavaScript "this". The this can be changed depending on the context being used. The usefulness of these methods comes when you want to do some method or function borrowing. Without further due, let's master this methods with examples.
The call(), apply(), and bind() method all do the same thing with some slight variation.
Method borrowing in JavaScript is the concept of reusing an exiting method within the context of different object or reuse method outside the context with which it was created.
Say object A has a method f, object B should be able to use method f of A if the same property(ies) are present in both object.
Let's illustrate this concept in code.
Let's say objects A and B
//object A
let A = {
name: "Michael",
lastName: "Programmer",
getFullName(){
console.log(`The full name is ${this.name} ${this.lastName}`)
}
}
//object B
let B = {
name: "Another",
lastName: "Michael"
}
Borrowing
Now let's borrow the getFullName method of object A to output to the console details of object B
Call() method
call(thisArg: any, arg1, arg2...argn)
The call method accepts an argument list separated by commas. The first argument references the this keyword, which is the object you are trying to switch context to. In the example below, object B is this
A.getFullName.call(B); // The full name is Another Michael
Boom! that simple.
We could also rip out the method from the object A and have object A and object B borrow and use the function.
let namePrinter = function(){
console.log(`The full name is ${this.name} ${this.lastName}`);
};
//object A
let A = {
name: "Michael",
lastName: "Programmer"
}
//object B
let B = {
name: "Another",
lastName: "Michael"
};
namePrinter.call(A); //The full name is Michael Programmer
namePrinter.call(B); //The full name is Another Michael
Passing argument
In case you are wondering, we can also pass arguments let see this with an example. Suppose the namePrinter function also accepts and output a country. You can pass in the argument after referencing this. Let's create another function accepting an argument and let's borrow it. Let's also add objects C and D.
let namePrinterWithHomeTown = function (hometown) {
console.log(`${this.name} ${this.lastName} is from ${hometown}`);
}
//object C
let C = {
name: "Jack",
lastName: "Black"
};
//object D
let D = {
name: "Alaka",
lastName: "Kamba"
};
namePrinterWithHomeTown.call(A, "Serbia") // Michael Programmer is from Serbia
Apply() method
apply(thisArg: [args])
The apply method works the exact same way as the call method but it accepts an array of argument after referencing this.
namePrinter.apply(C) //The first name is Jack, last name is Black
Passing arguments
namePrinterWithHomeTown.apply(C, ["Madagascar"]) //Jack Black is from Madagascar
Bind() method
bind(thisArg, Args)
Bind behaves very similar to apply and call method with the only difference being bind is deferred which means it has to be manually invoked because it's not invoked automatically like call and apply. Let see this in code.
let objD = namePrinter.bind(D);
objD(); // The first name is Alaka, last name is Kamba
Passing argument
let nameCountry = namePrinterWithHomeTown.bind(C, "Peru");
nameCountry(); // Jack Black is from Peru
A great benefit of these methods is reusability. If you have multiple object having same or very similar shape, and you want to carry out a common operation across these objects, you can function borrow if you are not using prototypical inheritance.
Throughout the javascript ecosystem, the call, bind, & apply method can be used with almost anything in terms or attaching and switching contexts. Below is a playground to play around with these methods. Open up the console at the bottom right to see results.
I will explore some advance application of these methods in another post which will go in-depth to explain some powerful concepts.
Happy Coding!