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?

+6


source to share


3 answers


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

.

+9


source


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);

      

+1


source


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)());

      

http://jsfiddle.net/ev3z3td3/2/

+1


source







All Articles