在我自己的一些旧代码中,我使用以下内容:
Object.prototype.instanceOf = function( iface )
{
return iface.prototype.isPrototypeOf( this );
};
然后我做(例如)
[].instanceOf( Array )
这有效,但看起来以下情况也是如此:
[] instanceof Array
现在,这肯定只是一个非常简单的例子。因此,我的问题是:
a instanceof b
总是与b.prototype.isPrototypeOf(a)
相同吗?
答案 0 :(得分:27)
是的,他们做同样的事情,都遍历原型链,寻找其中的特定对象。
两者之间的区别是它们是什么,以及您如何使用它们,例如Object.prototype
对象上的isPrototypeOf
是一个函数,它允许您测试特定对象是否在另一个对象的原型链中,因为此方法在Object.prototype
上定义,可用于所有对象。
instanceof
是一个运算符,它需要两个操作数,一个对象和一个Constructor function,它将测试传递的函数prototype
属性是否存在于对象链(通过[[HasInstance]](V)
内部操作,仅在Function对象中可用)。
例如:
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
答案 1 :(得分:2)
IncrementCommand
始终与a instanceof b
相同吗?
否,b.prototype.isPrototypeOf(a)
的行为不一定总是与a instanceof b
相同。
Another answer指出,它们的区别是 (一个是运算符,另一个是b.prototype.isPrototypeOf(a)
对象上可用的内置方法)。这是正确的,但是在某些特殊情况下,Object.prototype
会产生a instanceof b
而TypeError
会很好,反之亦然。
b.prototype.isPrototypeOf(a)
的右侧应该是构造函数。
如果instanceof
不是函数:
b
将产生a instanceof b
。
TypeError
可以正常工作。
b.prototype.isPrototypeOf(a)
使用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
时,b.prototype.isPrototypeOf(a)
应该继承自b.prototype
:
如果Object.prototype
无法访问b.prototype
方法:
Object.prototype.isPrototypeOf()
将产生b.prototype.isPrototypeOf(a)
。TypeError
可以正常工作。
a instanceof b
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
建立的原型继承,而不使用构造函数,则可能应该使用Object.create()
方法。 (实际上,Object.prototype.isPrototypeOf()
的使用情况受到了更多限制,因为instanceof
期望其右侧参数是构造函数。)instanceof
运算符会稍微安全一些。 (您将能够涵盖instanceof
不在Object.prototype
原型链中的情况)答案 2 :(得分:1)
运算符优先级和真实性不同,因为一个是表达式,另一个是方法调用。需要强调的一点是,遍历原型链,因此您不能假设匹配的原型与相关对象之间存在一对一的映射:
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));
}
}
<强>参考强>