apply
, call
and bind
are methods that can be called on any JS function and are used to call that function in a specified scope. this
inside the function will refer to the specified scope. The specified scope can be different from the scope in which the function was defined.
apply
and call
methods
apply
and call
have just a slight difference in their signature. Both take in scope as the first argument. apply
takes an Array of function arguments as the second argument. call
takes these arguments sequentially second argument onwards. Both apply
and call
execute the function immediately.
Let’s try to understand apply
and call
methods using code snippets.
Snippet 1
const cat = {
name: 'cat',
greet: function() {
console.log(`Hello, I am a ${this.name}.`);
}
}
const dog = {
name: 'dog'
}
cat.greet(); // Prints - Hello, I am a cat.
cat.greet.call(dog); // Prints - Hello, I am a dog.
cat.greet.apply(dog); // Prints - Hello, I am a dog.
In the above snippet, we can see that both apply
and call
behave the same way. Also since greet
does not have any arguments, both apply
and call
usages look the same. In the next snippet, let's see example with arguments.
Snippet 2
const cat = {
name: 'cat',
greet: function() {
console.log(`Hello, I am a ${this.name}. Second argument: ${arguments[1]}`);
}
}
const dog = {
name: 'dog'
}
cat.greet.call(dog, 1, 2); // Prints - Hello, I am a dog. Second argument: 2
cat.greet.apply(dog, [1, 2]); // Prints - Hello, I am a dog. Second argument: 2
In the above snippet, we can see the only difference apply
and call
usages. apply
takes in an Array of arguments that are passed to the function while calling. call
takes these arguments one by one.
bind
method
bind
method returns a new function. This new function, when called, makes the call to the original function in the specified scope. Arguments can be passed at 2 places - one at the time of binding, and the second at the time of the new function call. Check out the 'snippet 4' below to get to know what happens with these arguments.
Snippet 3
const cat = {
name: 'cat',
greet: function() {
console.log(`Hello, I am a ${this.name}. Second argument: ${arguments[1]}`);
}
}
const dog = {
name: 'dog'
}
const newFunction = cat.greet.bind(dog); // greet is not called yet.
newFunction(1, 2); // Prints - Hello, I am a dog. Second argument: 2
In the above snippet, we can see that the bind
method does not call the greet
function. It returns a newFunction, which can be called later.
Snippet 4
const cat = {
name: 'cat',
greet: function() {
console.log(`Hello, I am a ${this.name}. All argument: ${Array.from(arguments)}`);
}
}
const dog = {
name: 'dog'
}
const newFunction = cat.greet.bind(dog, 1, 2); // greet is not called yet.
newFunction(3, 4); // Prints - Hello, I am a dog. All argument: 1,2,3,4
In the above snippet, 2 arguments (say a1) are passed at the time of bind. Another 2 arguments (say a2) are passed at the time of the call to the new function. From the data which is printed, we can see that a1 and a2 are all passed to the greet function, and a1 precede a2.