简体   繁体   中英

What's the difference between isPrototypeOf and instanceof in Javascript?

In some of my own older code, I use the following:

Object.prototype.instanceOf = function( iface )
{
 return iface.prototype.isPrototypeOf( this );
};

Then I do (for example)

[].instanceOf( Array )

This works, but it seems the following would do the same:

[] instanceof Array

Now, surely this is only a very simple example. My question therefore is:

Is a instanceof b ALWAYS the same as b.prototype.isPrototypeOf(a) ?

Yes, they do the same thing, both traverse up the prototype chain looking for an specific object in it.

The difference between both is what they are , and how you use them, eg the isPrototypeOf is a function available on the Object.prototype object, it lets you test if an specific object is in the prototype chain of another, since this method is defined on Object.prototype , it is be available for all objects.

instanceof is an operator and it expects two operands, an object and a Constructor function , it will test if the passed function prototype property exists on the chain of the object (via the [[HasInstance]](V) internal operation, available only in Function objects).

For example:

function A () {
  this.a = 1;
}
function B () {
  this.b = 2;
}
B.prototype = new A();
B.prototype.constructor = B;

function C () {
  this.c = 3;
}
C.prototype = new B();
C.prototype.constructor = C;

var c = new C();

// instanceof expects a constructor function

c instanceof A; // true
c instanceof B; // true
c instanceof C; // true

// isPrototypeOf, can be used on any object
A.prototype.isPrototypeOf(c); // true
B.prototype.isPrototypeOf(c); // true
C.prototype.isPrototypeOf(c); // true

Is a instanceof b ALWAYS the same as b.prototype.isPrototypeOf(a) ?

No, a instanceof b will not always behave the same as b.prototype.isPrototypeOf(a) .

CMS' answer pointed out that they differ in what they are (one is an operator and the other is a built-in method available on the Object.prototype object). This is correct, however there are also some special cases for which a instanceof b will result in a TypeError while b.prototype.isPrototypeOf(a) will work just fine and vice versa.

Difference #1

The right-hand side of instanceof is expected to be a constructor function.

If b is not a function:

  • a instanceof b will result in a TypeError .

  • b.prototype.isPrototypeOf(a) will work just fine.

 const b = { prototype: {} }; const a = Object.create( b.prototype ); console.log( b.prototype.isPrototypeOf(a) ); // true console.log( a instanceof b ); // TypeError: Right-hand side of 'instanceof' is not callable 

Difference #2

When using b.prototype.isPrototypeOf(a) , b.prototype should be inheriting from Object.prototype :

If b.prototype has not access to the Object.prototype.isPrototypeOf() method:

  • b.prototype.isPrototypeOf(a) will result in a TypeError .
  • a instanceof b will work just fine.

 function B() {}; B.prototype = Object.create( null ); const a = new B(); console.log( a instanceof B ); // true console.log( B.prototype.isPrototypeOf(a) ) // TypeError: B.prototype.isPrototypeOf is not a function 

Difference #3

If the right-hand side of instanceof is a bound function, it is treated equivalently to its target function.

If b is a bound function:

  • a instanceof b will work just fine.
  • b.prototype.isPrototypeOf(a) will result in a TypeError (bound functions don't have a prototype property).

 function B() {}; const BoundB = B.bind( null ); const a = new B(); console.log( a instanceof BoundB ); // true console.log( BoundB.prototype.isPrototypeOf(a) ) // TypeError: Cannot read property 'isPrototypeOf' of undefined 

Conclusion

  • If you are dealing with prototypal inheritance established through Object.create() , without the use of constructors, you should probably be using the Object.prototype.isPrototypeOf() method (indeed the use cases of instanceof are more restricted in that instanceof expects its right-hand side parameter to be a constructor function).
  • If you are dealing with constructors you will be slightly safer by using the instanceof operator (you will be able to cover bound functions as well as the cases where Object.prototype does not lie in the prototype chain of Constructor.prototype ).

Operator precedence and truthiness differ since one is an expression and the other is a method call. One thing to emphasize is that both , so you cannot assume that there is a one-to-one mapping between a matching prototype and the object in question: ,因此您不能假设匹配的原型与相关对象之间存在一对一的映射:

 var i = 0; function foo() { console.log("foo"); console.log(i++ + ": " + Object.prototype.isPrototypeOf(Object) ) //true console.log(i++ + ": " + Function.prototype.isPrototypeOf(Function) ) //true console.log(i++ + ": " + Function.prototype.isPrototypeOf(Function) ) //true console.log(i++ + ": " + Function.prototype.isPrototypeOf(Object) ) //true console.log(i++ + ": " + RegExp.prototype.isPrototypeOf( RegExp(/foo/) ) ) //true console.log(i++ + ": " + Object.prototype.isPrototypeOf( RegExp(/foo/) ) ) //true console.log(i++ + ": " + Function.prototype.isPrototypeOf( RegExp(/foo/) ) ) //false console.log(i++ + ": " + Object.prototype.isPrototypeOf(Math) ) //true console.log(i++ + ": " + Math.isPrototypeOf(Math) ) //false } function bar() { console.log("bar"); console.log(i++ + ": " + (Object instanceof Object) ) //true console.log(i++ + ": " + (Function instanceof Function) ) //true console.log(i++ + ": " + (Function instanceof Object) ) //true console.log(i++ + ": " + (RegExp(/foo/) instanceof RegExp) ) //true console.log(i++ + ": " + (RegExp(/foo/) instanceof Object) ) //true console.log(i++ + ": " + (RegExp(/foo/) instanceof Function) ) //false console.log(i++ + ": " + (Math instanceof Object) ) //true console.log(i++ + ": " + (Math instanceof Math) ) //error } try { foo() } catch(e) { console.log(JSON.stringify(e)); } finally { try { bar(); } catch(e) { console.log(JSON.stringify(e)); } } 

References

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM