In a nutshell, .bind()
returns a new function that when called will call the original function with a specific this
value and (optionally) some new arguments preprended to the argument list.
.bind()
is used when you need to pass a callback (e.g. some sort of function reference), but you want the caller to call your function with a specific this
value. This is most common when your function is actually a method and you want the this
value set to be the a specific object so the method will operate on that specific object . If you don't use .bind()
in those cases, then the this
value will be determined by the caller (not you) and if the caller doesn't set it specifically, it will end up being the global object or (in strict mode) undefined
. If what you were passing was a method that relies on a specific value of this
in order to do its job, it would not work properly with the wrong this
value.
So, if you want to control the value of this
when your callback is called, you can use .bind()
. Internally, .bind()
just creates a small stub function that just remembers the this
value you pass it and calls your function with .apply()
to set the this
value. .bind()
is not magic as it can be done manually too.
.bind()
also has the capability to add extra arguments to the function so, if you want to add arguments beyond what the normal caller of the callback uses, you can specify those with .bind()
too. It creates a stub function that will add these extra arguments and set the this
value.
Let's say you have your Person
object and you want to hook a button up to the .say()
method for a particular Person
object.
<button id="talk">Talk</button>
And, if you tried this javascript:
"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", bob.say);
What you would find is that the say()
method is called, but it would be missing two things. It would be missing the right this
reference (which would be set to the button
object because that's how addEventListener calls its callbacks) and it would be missing the argument that say(message)
expects.
So, you could solve this yourself with your own stub function that calls bob.say()
with all the right arguments:
"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", function(e) {
bob.say("Hello");
});
Or, you could use .bind()
:
"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", bob.say.bind(bob, "Hello"));
There is no magic in .bind()
. It can be entirely simulated in javascript. In fact, here's a polyfill for it from MDN:
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
This may look more complicated than it is because of all the error checking, but it's really just return a new function that combines two sets of arguments and then calls the original function with a specific this
value.