Today I'll be walking through my simple, less robust reimplentation of Function.prototype.bind() which, along with apply() and call(), allows us JavaScript developers use functions outside of their defined execution context. However, unlike apply() and call(), bind returns a function bound to the specified context (instead of immediately invoking the function in the new context). The information in this paragraph alone is enough to start implementing bind, but in case it's not obvious, let's continue.

So, what do we mean when we say we're "binding" a function to an "execution context?" In short, "setting a function's execution context" sets its value of this to the specified context. Say we had an object called alice:

var alice = {
	name: 'alice',
    shout: function() {
    	console.log('Hey' + this.name + '!');
    }
}

Calling alice.shout() will log 'Hey alice!'. Simple. But what if we wanted to have an object bob with a 'name' property of 'bob' to shout as well, without repeating ourselves by rewriting the function? Well then we'd need to apply the function to our object:

alice.shout.apply(bob);	// 		logs 'Hey bob!'

The main (and maybe only) difference between call and apply is the function signature; call takes in a context and the arguments as individual parameters, whereas apply takes in the context and an array of arguments. With this understanding of call and apply, we now have enough information to implement bind.

The Solution

Function.prototype.bind = function(context) {
	var args = Array.prototype.slice.call(arguments, 1);
    var funcToBind = this;
    return function() {
    	var boundFuncArgs = Array.prototype.slice.call(arguments);
        return funcToBind.apply(context, args.concat(boundFuncArgs));
    }
}

The bind function takes in one specified argument (the desired context) and (as well as optional arguments that may be closure-scoped to the bound function). The second line stores these arguments in an array called args. We'll also create a temporary variable funcToBind to hold a reference to our function since the keyword this will take on new meaning within the function we return.

This returned function will also have its own variables stored in an array called boundFuncArgs. Then we return the value of calling funcToBind in the specified context with the arguments being the closure-scoped args concatenated with the boundFuncArgs.

So using bind, we can now return a function specific to logging bob.name:

var bobShout = alice.shout.bind(bob)
bobShout()	// logs 'Hey bob!'

One Use Case

One common use of bind is within a setTimeout call. Say we wanted to call alice.shout() 2 seconds from now. We could write the function like this, but it would fail:

setTimeout(alice.shout, 2000);	// logs undefined

This fails because setTimeout only immediately stores a reference to the function; when this function is executed 2 seconds from now, its execution context (and thus, the keyword this) will be set to the global (or in the browser, window) object, which doesn't have a property name.

If, however, we were to bind the function to alice, we could execute this code flawlessly:

setTimeout(alice.shout.bind(alice), 2000); 	// logs 'Hey alice!'

To reiterate, this works because at the time bind is being called (the same time setTimeout is storing the function reference), bind is returning us the same function with the keyword this permanently bound to the specified context, which in this case is the object alice.

I hope this clarifies some of the confusion about bind, though it seems to me that we may have passed that confusion on to how the this keyword works, which I'll tackle in a later post.