Wrapping your Brain Around JavaScript's Bind Method

JavaScript keyword this

I think everyone can agree that fully understanding JavaScript’s keyword this is…challenging. The object to which it refers changes depending upon the context in which it is called. Fortunately, you can use JavaScript’s native bind method to take control of matters. The code below demonstrates both the need for the bind method and works up to explain how exactly it work.

//Make a new object and a related(ish) function
var cat = {appetite: "hungry"}; 
var feedCat = function(){ this.appetite = "full"; }; 

//attempt to call the method on the object
cat.feedCat();

This doesn’t work, because feedCat isn’t a property of the cat object. Similarly, feedCat(cat) won’t work, because the this inside of feedCat will be bound to window. However, we can use JavaScript’s call or apply methods to manually bind this to the cat object:

feedCat.call(cat);

However, if we try to use a browser method, such as setTimout, funny things start to happen:

setTimeout(feedCat.call(cat), 10000);

The code above doesn’t work, because the feedCat function is invoked immediately and doesn’t return a function to be invoked later. So setTimeout is essentially trying to call undefined, not a function.

It is tempting imagine that any easy fix might be simply adding the feedCat function as a property of cat.

cat.feedCat = feedcat;

Unfortunately, setTimeout(cat.feedcat, 1000) still won’t work because setTimeout belongs to the window object, so when we call functions with it, this automatically binds to the window object (or other global object)! One of my Hack Reactor peers wrote up a more detailed explanation of that problem here.

We must use a wrapper function instead:

setTimeout(function(){feedCat.call(cat);}, 10000);

The wrapper function doesn’t get called until later, can because feedCat.call(cat) is inside of the wrapper function, it doesn’t get called until that function is called.

So now, let’s imagine that instead of using an anonymous wrapper function, we have a function called bind that does essentially the same thing. It’s code would need to look something like this:

var bind = function(func, args){
    func.call(args);
 }

Notice that the first parameter is the function we really want to call, and the second parameter is the object to which we want to bind this; any additional parameters could be passed to the interior function.

We could then run this code:

setTimeout(bind(feedCat, cat), 10000);

And that’s basically all the bind function does. It essentially cements the keyword this to whatever you want it to be. Instead of a rewriting bind everytime we want to use it with a different function, JavaScript has attached it as a method to the Function prototype. Because all functions delegate here, all functions have access to bind, so we would actually call it like this:

setTimeout(feedCat.bind(cat), 10000);

The real source code looks something like this:

Function.prototype.bind = function(context){ 
    var fn = this; 
    return function(){ return fn.apply(context, arguments); 
        }; 
    };

Using apply instead of call accounts for slightly more complicated situations in which many parameters must be passed in to the interior function. It also uses returns to account for the fact that most functions will need to return something, and not just implement a side effect like in ouf feedCat function.

Written on July 6, 2015