Wrapping your Brain Around JavaScript's Bind Method
JavaScript keyword thisI 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:
However, if we try to use a browser method, such as setTimout
, funny things start to happen:
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
.
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:
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:
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:
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:
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.