Good question. Let's start off by considering an example that's come up on StackOverflow before: mapping all the strings in an array to lowercase. Of course I can write
strings . map(function(string) { return string.toLowerCase(); })
but that seems a bit verbose. I'd rather write
strings . map(CALL_LOWERCASE_WITH_ELT_AS_THIS)
So I might try
strings . map(String.prototype.toLowerCase)
or, to use the shorter idiom some prefer
strings . map(''.toLowerCase)
because ''.toLowerCase is exactly equal to String.prototype.toLowerCase.
But this won't work, of course, because map passes each element to the specified function as its first argument, not as its this. Therefore, we need somehow to specify a function whose first argument is used to call some other function as its this. That, of course, is exactly what Function.call does:
function.call(context)
The first argument to call ("context") is used as the this when calling function.
So, problem solved? We ought to be able to just say:
strings . map(''.toLowerCase.call)
and people have tried this and then wonder why it didn't work. The reason is that even though we are passing call of toLowerCase as the callback to map, map still has no idea that the callback is supposed to be called with a this of ''.toLowerCase. We need to explicitly tell map which this to use to call the function, which in the case of map we can do with its second "context" argument:
strings . map(''.toLowerCase.call, ''.toLowerCase)
Actually, since call is the same on any function object, we can simplify this to just
strings . map(Function.call, ''.toLowerCase)
This works and gets the job done beautifully.
However, whereas map provides this second "context" argument to specify the this to call the callback with, that is not something we can depend on being available in all situations. We need a more general way to say "make a function which calls Function.call with some particular function as this".
That is exactly what bind does. It says "take a function and make another function which calls it with a particular this":
function.bind(context)
In our case, what we want to do is to "take the function Function.call and make another function which calls it with a this of ''.toLowerCase. That is simply
Function.call.bind(''.toLowerCase)
Now we can pass this to map without having to use the second argument:
strings . map(Function.call.bind(''.toLowerCase))
That works exactly the same as strings . map(Function.call, ''.toLowerCase), because in general map(fn, ctxt) is precisely equal to map(fn.bind(ctxt)).
The following breaks this down into a readable form, step by step:
Function . // From the Function object
call . // take the `call` method
bind( // and make a new function which calls it with a 'this' of
''.toLowerCase // `toLowerCase`
)
When this construct is specified as a callback, such as to map, it means:
Invoke call with the first argument passed in and ''.toLowerCase as this, which by virtue of the definition of call, means to call toLowerCase with that argument as this.
Some people prefer to simplify this a bit by saying
var call = Function.call;
var toLowerCase = ''.toLowerCase;
strings . map(call.bind(toLowerCase))
or, using the second argument provided by map, just
strings . map(call, toLowerCase)
which is almost readable as English: "map each string to the result of calling toLowerCase.
Another common, related use case would be specifying the callback in a then on a promise. Consider the following code:
promise . then(function(result) { result.frombulate(); })
That's fine, but it's a bit verbose. And then has no way to pass in a context to be used as this when invoking the success or failure handler. But with the above, we can now write:
promise . then(call.bind(frombulate))
There are other use cases for the call.bind idiom, but this is one of the most common ones: define a callback whose effect is to invoke some function with the parameter passed to the callback as its this.
With ES6 fat arrow functions, of course, I can write
promise . then(result => result.frombulate())
so there is relatively less advantage in the shorthand offered by call.bind(frombulate), and it is hard to deny that the fat-arrow version is more readable than that using bind.
The following question might be of interest too: Array.map and lifted functions in Javascript.