Creating Bound Functions with Function#bind
Originally published in the A Drip of JavaScript newsletter.
Continuing from some of our previous discussions of functions as first-class values, it's time to tackle Function
's bind
method. As you might guess, the purpose of bind
is to "bind" a function. But what does that mean, exactly?
var hero = {
name: "Batman",
signal: function () {
console.log(this.name + " has been signaled.");
}
};
// Outputs: "Batman has been signaled."
hero.signal();
Consider if we wanted to let another object signal Batman. We could do something like this:
var commissioner = {
name: "Jim Gordon",
signalBatman: function() {
hero.signal();
}
};
// Outputs: "Batman has been signaled."
commissioner.signalBatman();
But what if the hero
variable gets redefined?
hero = {
name: "Superman",
signal: function () {
console.log(this.name + " has been signaled.");
}
};
// Outputs: "Superman has been signaled."
commissioner.signalBatman();
Commissioner Gordon is signaling Superman? That can't be right. Let's try using bind
instead.
var hero = {
name: "Batman",
signal: function () {
console.log(this.name + " has been signaled.");
}
};
var commissioner = {
name: "Jim Gordon",
signalBatman: hero.signal.bind(hero)
};
hero = {
name: "Superman",
signal: function () {
console.log(this.name + " has been signaled.");
}
};
// Outputs: "Batman has been signaled."
commissioner.signalBatman();
As you can see, the bind
method allows us to create a new function which is permanently bound to a given value of this
. You can't even override its this
value using call
or apply
. This can be quite handy when you need to pass around a function that needs a certain this
value in order to function correctly.
For instance, consider good old console.log
:
// Outputs: "logging"
console.log("console.logging");
var justLog = console.log;
// TypeError: Illegal invocation
justLog("just logging");
It turns out that log
just won't work without console
. But is there a way we can just pass around the function instead of the entire console object? With bind
there is.
// Outputs: "logging"
console.log("console.logging");
var justLog = console.log.bind(console);
// Outputs: "just logging"
justLog("just logging");
Unfortunately, bind
is only supported in Internet Explore 9 or higher. If you need this functionality in older browsers, you can use Underscore, Lo-Dash, or the ES5 shim library.
That's a brief introduction to creating bound functions with bind
. Next time we'll look at using bind
for partial application.
Thanks for reading!
Joshua Clanton