Search code examples
javascriptecmascript-5

Why does .bind() prepend the optional arguments?


The first time I used .bind() I was tripped up by the fact that the optional arguments passed to the bound function are prepended. This got me when I was trying to hand things off to anonymous event handling functions, sort of like this:

$('#example').on('change', function(arg1, arg2, evt) {
    console.log(evt, arg1, arg2);
}.bind(null, arg1, arg2));

The MDN for .bind() mentions the prepending several times but never elaborates, so I'm curious as to why - why do I have to put arg1 and arg2 before the evt in the function arguments? Wouldn't appending be easier to understand and slightly more performant?


Solution

  • If the additional bound parameters were appended to the call time arguments, the behaviour would be like this:

    function foo(bar, baz) {}
    const b = foo.bind(null, 42);
    
    b();          // bar = 42
    b('c');       // bar = 'c', baz = 42
    b('c', 'd');  // bar = 'c', baz = 'd'
    

    Meaning, it is unpredictable where your bound arguments will end up, which is arguably insane.

    Prepending also makes more sense if you think of bind as partial application or currying: very loosely functionally speaking, foo.bind(null, 42) returns a partially applied function,
    it turns a -> b -> c (a function which takes two values and returns a third)
    into b -> c (a function which takes only one more value and returns another).