When to use .bind () in JS
There are a ton of blogs and posts out there on how to use bind()
and how it differs from call()
and apply()
, but there are very few examples on or not. why should you usebind()
I found that many of the examples given are very unusual events such as:
"use strict";
function Person(firstName, lastName){
this.firstName = firstName
this.lastName = lastName
}
Person.prototype.say = function(message){
return '[' + this + ']: ' + this.firstName + ' ' + this.lastName + ' said: "' + message + '"'
}
Person.prototype.toString = function(){
return '[Person]'
}
moe = new Person("Mo", "El")
func = moe.say.bind(moe)
console.log(func("asdasda"))
I don't know when there is a time when I want to make a function equal to some other variable and use that variable instead of the original function, let alone this variable equal to the binding of the instance of the Person
object.
Good examples?
source to share
In a nutshell, it .bind()
returns a new function that, when called, will call the original function with a specific value this
and (optionally) some new arguments preceded by an argument list.
.bind()
used when you need to pass a callback (like some kind of function reference), but you want the caller to call your function with a specific value this
. This is most common when your function is actually a method and you want the value to be this
set to a specific object in order for the method to work on that specific object. If you don't use .bind()
in these cases, then the value this
will be determined by the caller (not you), and if the caller doesn't customize it specifically, it becomes a global object or (in strict mode) undefined
. If what you've been going through is a method that relies on a specific value this
to do its job, it won't work as expected with the wrong value this
.
So, if you want to control the value this
when the callback is called, you can use .bind()
. Internally .bind()
creates a little stub function that simply remembers the value this
you pass in and calls your function with .apply()
to set the value this
. .bind()
is not magic, as it can be done manually too.
.bind()
also has the ability to add additional function arguments, so if you want to add arguments outside of what a normal caller callback uses, you can also specify those that have .bind()
. It creates a stub function that will add these additional arguments and set the value this
.
Let's say you have your object Person
and you want to hook a button to a method .say()
for a specific object Person
.
<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 will find is that the method is called say()
, but it is missing two things. It will be missing the correct reference this
(which will be set to the object button
, because that's how addEventListener calls its callbacks) and it will be missing the argument expected say(message)
.
So, you can solve this yourself with your own stub function that calls bob.say()
with all the correct arguments:
"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", function(e) {
bob.say("Hello");
});
Or you can use .bind()
:
"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", bob.say.bind(bob, "Hello"));
There is .bind()
no magic. It can be fully modeled 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;
};
}
It might look more complicated than error checking, but it really just returns a new function that concatenates two sets of arguments and then calls the original function with a specific value this
.
source to share
Use bind()
if you want the function to always be executed with a special value this
.
It is useful for more functional programming when passing functions as callbacks or event handlers.
var User = function(name) { this.name = name; };
User.prototype.poke = function() { alert "Hey, don't poke " + this.name; };
var bob = User('Bob');
// assume jQuery for brevity, and because it screws with `this` in callbacks
$('#some-element').click(bob.poke.bind(bob));
This will warn you "Hey, don't poke Bob" because you passed a bound function to him. So if this element was explicitly about Bob, it makes sense to bind an event handler to it.
But there are other ways to do it without bind
, of course.
$('#some-element').click(function() {
bob.poke();
});
The difference can be a matter of style. And it bind
didn't have much support in all browsers, so many JS programmers figured out other ways to do this, and many other ways are still in use today.
One clear benefit is when you want to pass the same function to many different places and you want to explicitly install this
.
var bobPoke = bob.poke.bind(bob);
onFoo(bobPoke);
onBar(bobPoke);
onBaz(bobPoke);
source to share
This is perhaps the easiest way to explain it in a practical sense. Since most of the answers provided a theoretical definition and explanation, I will show a simple use case. You should use bind when you want the called function to have a different value than the default.
var NS = {
user : "self",
getUser : function() { return this.user; }
};
var CLOSURE = NS.getUser;
// error user is undefined, "this" in that context refers to the global object, "window"
console.log(CLOSURE());
// Bind the function call to NS object
console.log(CLOSURE.bind(NS)());
source to share