On Mozilla Developer Center, there is a page about the Function.prototype.bind
function and provides a compatibility function for browsers which do not support this function.
However, when analyzing this compatibility code I cannot find out why they use instanceof nop
. nop
has been set to function() {}
. What part of the ECMA specification on bind
does this correspond with? And what variables are an instance of function() {}
?
The following returns false
, so I don't completely know what it is used for. What things return true when doing an instanceof function() {}
check?
(function() {}) instanceof (function() {}) // false
The code is as follows:
Function.prototype.bind = function( obj ) {
if(typeof this !== 'function')
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : ( obj || {} ),
args.concat( slice.call(arguments) ) );
};
bound.prototype = this.prototype;
return bound;
};
instanceof is a binary operator we use to test if an object is of a given type. The result of the operation is either true or false. It's also known as a type comparison operator because it compares the instance with the type. Before casting an unknown object, the instanceof check should always be used.
The JavaScript instanceof operator is used to check the type of an object at the run time. It returns a boolean value(true or false). If the returned value is true, then it indicates that the object is an instance of a particular class and if the returned value is false then it is not.
The isInstance method is equivalent to instanceof operator. The method is used in case of objects are created at runtime using reflection. General practice says if the type is to be checked at runtime then use the isInstance method otherwise instanceof operator can be used.
The typeof and the instanceof operator is quite different. typeof returns a type of entity that it's operated on. instanceof of returns true if an object is created from a given constructor and false otherwise. All non-primitive objects are instances of Object , so that'll always return true .
Someone edited out the part that makes it useful. Here's what it used to look like:
Function.prototype.bind = function( obj ) {
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : ( obj || {} ),
args.concat( slice.call(arguments) ) );
};
// These lines are the important part
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
I answered another question that was asking the same thing (but when the code was correct) here: mozilla's bind function question.
The reason for the this instanceof nop
check is so that if you call the bound function as a constructor (i.e. with the new
operator), this
is bound to the new object instead of whatever you passed to bind
.
To explain the "important part", nop
is basically getting inserted into the prototype chain so that when you call the function as a constructor, this
is an instance of nop
.
So if you run var bound = original.bind(someObject);
the prototype chain will look like this:
original | nop | bound
My guess for why they used nop
instead of this instanceof self
is so that the bound function would have it's own prototype
property (that inherits from self
's). It's possible that it's not supposed to which could be why it got partially edited out. Regardless, the code as it is now is not correct, but will work as long as you don't use the function as a constructor.
There seems to be an error with that implementation. nop
is never used (to instantiate anything) expect for that instanceof
check, which can never be true for anything since no object can be instantiated from nop
, which is buried deep in that closure.
Consider this:
// Identical definition, but different Function instances
var nop = function () {},
mop = function () {};
var obj1 = new mop;
obj1 instanceof mop // true
obj1 instanceof nop // false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With