Alexander Mills
Alexander Mills

Reputation: 100190

Implementation of Function.prototype.bind

Is this implementation of JavaScript's Function.prototype.bind more or less correct?

Function.prototype.bindTemp = function () {

    const fn = this;
    var args = Array.prototype.slice.apply(arguments);
    const ctx = args[0];
    args = args.slice(1);

    return function () {
        return fn.apply(ctx, args.concat(Array.prototype.slice.apply(arguments)));
    }

};

anything obviously wrong or missing?

Upvotes: 1

Views: 906

Answers (2)

Bergi
Bergi

Reputation: 664970

You've got the main idea, but if you look closely enough (at the spec) there are some points that are rather less correct:

  • bind should immediately throw a TypeError when not called upon a function
  • bind.length should be 1
  • the bound functions should not rely on the original to have an .apply method
  • the bound functions should not have a .prototype property
  • the bound functions should construct an instance of the same type as the original when invoked with new1
  • the bound functions should have the same prototype as the original2
  • the bound functions should have a .length that equals the arity of the original minus the number of bound arguments3
  • the bound functions should have a .name that contains the name of the original3

You'll find a better polyfill at MDN.

1: This cannot reliably distinguished prior to ES6. And to be pedantic, the bound functions should only be constructible at all if the original is as well.
2: This only became relevant as of ES6.
3: This can only be implemented with some kind of eval magic prior to ES6.

Upvotes: 3

coyotte508
coyotte508

Reputation: 9725

As bind was not always cross browser, there was a polyfill for it, and it's mentioned in this question as well: Javascript's Bind implementation?

/*1*/       Function.prototype.bind = function ()
/*2*/       {
/*3*/           var fn = this,
/*4*/               args = Array.prototype.slice.call(arguments),
/*5*/               object = args.shift();
/*6*/           return function ()
/*7*/           {
/*8*/               return fn.apply(object,
/*9*/                   args.concat(Array.prototype.slice.call(arguments)));
/*10*/           };
/*11*/       };

The implementation (from John Resig's book) is the same as yours (nearly), so there shouldn't be anything wrong.

EDIT:

Returning a function created with () => instead of function() would avoid you storing the this variable into fn, as arrow functions bind the this above.

Upvotes: 1

Related Questions