Function.bind.bind(Function.bind)(Function.call)

In javascript a function can be executed with different execution contexts. For javascript developers this is a walk in the park. But it turns out that when you make more than one walk in the park, you can easily get lost!

1
2
var bindable = Function.bind.bind(Function.bind);
var callable = Function.bind.bind(Function.call);

In this post I explain how this works and that bindable and callable are actually useful!

Function.bind

Before we start digging, its important to understand Function.bind internals. To do this, we will create our very own bind.
Now, to make sure we’re all on the same page, here is a definition

The bind() method creates a new function that, when called, has its this keyword set to the provided value,
with a given sequence of arguments preceding any provided when the new function is called.

plus a couple of test cases

1
2
3
4
Array.prototype.toString.bind([1,2,3])();    // equals: [1,2,3].toString()

log = console.log.bind(console);
log('hello world');                          // equals: console.log('hello word')

Feel free to create one yourself before reading on and see if you can do this!

Here is my very minimalistic implementation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Function.prototype.bind = function bind(fToBind) {
    var self = this;

    return function () {
        return self.call(fToBind);
    }
}

Array.prototype.toString.bind([1,2,3])(); //  --> "1,2,3"
log = console.log.bind(console);
log('hello world'); // --> Ooops: nothing printed in the console

To fix this we need the arguments passed to bind combined with the arguments from the inner function as call‘s second argument

1
2
3
4
5
6
7
8
9
Function.prototype.bind = function (fToBind) {
    var self = this,
          args = Array.prototype.slice.call(arguments, 1);

    return function () {
        return self.apply(fToBind,
            args.concat(Array.prototype.slice.call(arguments)));
    };
};

Callable

A callable is a function which executes an other function with a specific execution context

1
2
3
var callable = Function.bind.bind(Function.call);
var log = callable(console.log, console);
log('hello world'); // --> "hello world"

To understand the whole flow, for each step I write down the function which our bind returns

1
2
3
4
5
6
7
8
9
var callable = function (arg1, arg2) {
    return Function.bind.apply(Function.call, [arg1, arg2]);
}

var log = function (arg1) {
    return Function.call.apply(console.log, [console, arg1]));
}

Function.call.apply(console.log, [console, 'hello world'])) // log('hello world')

If you look closer to the last line, you’ll noticed it is the same thing as

1
console.log.call(console, 'hello world')

Bindable

One good use case for a bindable is that it can create a callable

1
2
var bindable = Function.bind.bind(Function.bind);
var callable = bindable(Function.call);

Which means that the flow described earlier applies here as well, but you have to replace Function.call with Function.bind! But there are more interesting use cases. For example, it can be used to convert functions into methods

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function toString() {
    console.log('i = ' + this.i);
}

var instanceToString = bindable(toString);

function Test (i) {
    this.i = i || 0;
    this.toString = instanceToString(this);
}

new Test(10).toString()