Javascript中isPrototypeOf和instanceof有什么区别?

时间:2010-03-17 17:28:45

标签: javascript inheritance prototype instanceof

在我自己的一些旧代码中,我使用以下内容:

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

然后我做(例如)

[].instanceOf( Array )

这有效,但看起来以下情况也是如此:

[] instanceof Array

现在,这肯定只是一个非常简单的例子。因此,我的问题是:

a instanceof b 总是b.prototype.isPrototypeOf(a)相同吗?

3 个答案:

答案 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 bTypeError会很好,反之亦然。

差异#1

b.prototype.isPrototypeOf(a)的右侧应该是构造函数。

如果instanceof不是函数:

  • b将产生a instanceof b

  • TypeError可以正常工作。

b.prototype.isPrototypeOf(a)

差异#2

使用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));
    }
  }

<强>参考