A few days ago I was asked if I could tell the difference between apply, call and bind.
Both apply and call used to call functions and there are dozens of posts explaining how they do that.
They’re expecting this as their first argument, and if you ever read this clever comparison on Stack Overflow:
Think of a in apply for array of args and c in call for columns of args.
you’ll hardly ever forget what’s the only real difference.
apply expects the arguments after this in array-like form while call expects them individually.
Because of No Autobinding in React
I used bind regularly, but I still had no idea how it compared to apply or call, so here are my findings:
Similarities
- All three functions accept
thisas their first argument.bindis morecall-like meaning that it expects the arguments to be passed individually.
Differences
applyandcallused to invoke functions,bindcreates a new function. When you invoke this function it will has itsthiskeyword set to the value you provided as first argument.
var cat = {
name: 'Milu',
greet: function (greeting) {
return greeting + ', ' + this.name;
}
};
cat.greet.apply(cat, ['Hi']); // returns Hi, Milu
cat.greet.call(cat, 'Hello'); // returns Hello, Milu
var greetBound = cat.greet.bind(cat, 'Hey'); // returns a function
greetBound() // returns Hey, Milu
These things can be found in the documentation so let’s do something what isn’t there.
Invocation with Function objects
Below is a function purr, which in fact is a Function object. Every Function object has a
name property so the following call will result in:
function purr() {
return 'purrs at a frequency of 20 to 30 vibrations per second';
}
var greetBound = cat.greet.bind(purr, ['Hey']);
greetBound(); // returns Hey, purr
The same thing will happen when you call apply or call while providing purr as first argument.
Invocation with an array of arguments
Passing an array of arguments to bind then calling the bound function will have the same effect like
passing it to call:
var cat = {
name: 'Milu',
greet: function (greeting) {
return greeting + ', ' + this.name;
}
};
cat.greet.call(cat, ['Hi', 'Hello']); // returns Hi,Hello, Milu
var greetBound = cat.greet.bind(cat, ['Hi', 'Hello']);
greetBound(); // returns Hi,Hello, Milu
bind converts its second argument to string before passing it to the bound function.
When to use bind
Bind is really just a call except that the invocation of the bound function can be delayed.
This reminds us to callbacks functions. Sadly, most of the examples I encountered did use bind
with callback functions but they didn’t had the most thoughtful design,
which justified the usage of bind:
var Widget = function () {
this.counter = 0;
$('button').on('click', function () {
this.counter += 1;
$('span').text(this.counter);
}.bind(this));
};
A simpler widget:
var Widget = function () {
var counter = 0;
$('button').on('click', function () {
counter += 1;
$('span').text(counter);
});
};
Browsing through dozens of examples I saw that bind is more extensively used where the code
has conventional object-oriented design - which I’ve been avoiding altogether when it comes to JavaScript, and it pretty
much explains why I had no idea how it compares to call and apply.
Do you have a specific scenario where bind is inevitable, or more appropriate? Let me know in the comments!