Search code examples
javascriptthisbindpartial-application

Explain Javascript's Function.prototype.bind browser shim


I'm just trying to really understand the following code which is from MDN. Its the shim for Function.prototype.bind:

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          return fToBind.apply(this instanceof fNOP && oThis
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

First off, why is aArgs initially ignoring the first argument in the arguments list?

Secondly, why is fToBind taking the aArgs array and concatenating the rest of the arguments after? Wouldn't this create an array with args 1 to n concatenated with args 0 to n?

I'm so confused!


Solution

  • First off, why is aArgs initially ignoring the first argument in the arguments list?

    Because the first argument is the value that this will be set to (oThis). We don't want to pass that as argument to the function later on.

    Secondly, why is fToBind taking the aArgs array and concatenating the rest of the arguments after? Wouldn't this create an array with args 1 to n concatenated with args 0 to n?

    Yes. Note that those are different arguments sets. aArgs refers to the arguments passed to .bind(), while arguments refers to the arguments of the bound function fBound.

    We want to pass both, arguments that have been passed to .bind and the arguments that have been passed to the bound function. I.e. we want

    var fBound = f.bind(null, a, b); // aArgs = [a, b];
    fBound(c, d); // arguments = [c, d]
    

    to be equivalent to f(a, b, c, d).


    Basically it does everything so that the shim works like the .bind is expected to work. If you are confused by the implementation that you might needs to spend some more time to get a better understanding of .bind.