8

The MDN bind polyfill is shown below.

I am trying to work out the purpose of

this instanceof fNOP ? this : oThis

in the fToBind.apply invocation.

I can't get my head around it. Can someone help shed some light?

Function.prototype.bindMdn = 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 ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
    }
    ;
    if (this.prototype) {
        // Function.prototype doesn't have a prototype property
        fNOP.prototype = this.prototype;
    }
    fBound.prototype = new fNOP();
    return fBound;
};

It seems to be a short-circuit if an instance of the bound function is supplied as the target when invoking the bound function, but the typeof check should catch this, so I don't understand its presence.

Link to the MDN page:

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

Edit: This is a different question from the suggested duplicate. The suggested duplicate asks why fNOP is needed. I fully grok that.

This question is why the instanceof check is needed and what function it serves. I present my short-circuit hypothesis above, together with a reason why that doesn't fully make sense.

Ben Aston
  • 53,718
  • 65
  • 205
  • 331
  • 1
    Would you mind add link of MDN page please? – Morteza Tourani Jul 16 '16 at 15:07
  • @mortezaT [MDN: Function.prototype.bind() Polyfill](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill) – t.niese Jul 16 '16 at 15:08
  • Probably a duplicate of [MDN Function.prototype.bind bound function called as constructor](http://stackoverflow.com/questions/23693282) – t.niese Jul 16 '16 at 15:11
  • 1
    Possible duplicate of [MDN Function.prototype.bind bound function called as constructor](http://stackoverflow.com/questions/23693282/mdn-function-prototype-bind-bound-function-called-as-constructor) – Michael Liu Jul 16 '16 at 15:26
  • It is not a duplicate of that question. This is a fundamentally different question. – Ben Aston Jul 16 '16 at 15:27

1 Answers1

6

If you use the result of a .bind to create a new instance with new:

 function TestClass(a,b,c,d) {
 }

 var TestClassBound = TestClass.bindMdn(null, 1, 2, 3);

 new TestClassBound();

Then this instanceof fNOP is true.

The typeof this !== 'function' is just there to test if it was called a regular way on a function and not with call or apply or to make sure it was not copied to another objects prototype. So it only prevent something like

Function.prototype.bind.call("Not a function", 1, 2, 3);

Or

var testObj = {};
testObj.bind = Function.prototype.bind;

testObj.bind(1,2,3);

For every regular call of bind on a function the typeof this will always be function.

So the typeof this !== 'function' is to check if the object bind is called is really a function.

And the this instanceof fNOP within the fBind ensures that the behaviour is correct when the result of the binding is used.

t.niese
  • 39,256
  • 9
  • 74
  • 101
  • _"And the this instanceof fNOP within the fBind ensures that the behaviour is correct when the result of the binding is used."_ Which behavior ? My understanding is, when you prepend the function call with a `new`, the hard-bound function will be called with a plain new object bound to the hard-bound function's `this`, so `this instanceof fNOP` is the same as `[plain object created because of new] instanceof fNOP`, which means the condition will return false (since `fNOP`'s prototype does not exist in the prototype chain of the newly created object), which means `this` will be set incorrectly – doubleOrt Sep 23 '17 at 19:12
  • So `this` will be bound to `oThis`, which shouldn't be the case if the `new` operator is used, if the `new` operator is used, `this` should be bound to the new object created by the `new` operator behind-the-scenes. – doubleOrt Sep 23 '17 at 19:14
  • Moreover, what does `fNOP` stand for ? I assume the "f" is there for "function", what about the other three letters ? – doubleOrt Sep 23 '17 at 19:15
  • @Taurus `nop` is a common abbreviation for `no operation` and it is used when something is needed, even if it doesn't do anything itself. – t.niese Sep 24 '17 at 09:23
  • @Taurus I'm not sure what you want to say with the other comment. Do you think the implementation of MDN is wrong? – t.niese Sep 24 '17 at 09:27