51

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

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

然后我做(例如)

[].instanceOf( Array )

这可行,但似乎以下内容会做同样的事情:

[] instanceof Array

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

a instanceof b 总是一样吗b.prototype.isPrototypeOf(a)

4

3 回答 3

31

是的,它们做同样的事情,都遍历原型链,寻找其中的特定对象。

两者之间的区别在于它们是什么以及如何使用它们,例如isPrototypeOf是对象上可用的函数Object.prototype,它可以让您测试特定对象是否在另一个对象的原型链中,因为此方法是在 上定义的Object.prototype,所以它是可用于所有对象。

instanceof一个运算符,它需要两个操作数,一个对象和一个构造函数,它将测试传递的函数prototype属性是否存在于对象的链上(通过[[HasInstance]](V)内部操作,仅在函数对象中可用)。

例如:

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
于 2010-03-17T18:22:34.867 回答
5

a instanceof b总是一样吗b.prototype.isPrototypeOf(a)

不,a instanceof b不会总是表现得与b.prototype.isPrototypeOf(a).

CMS 的回答指出,它们的本质不同一个是运算符,另一个是对象上可用的内置方法Object.prototype)。这是正确的,但是也有一些特殊情况a instanceof b会导致一段TypeError时间b.prototype.isPrototypeOf(a)会正常工作,反之亦然。

差异#1

的右侧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

差异#2

使用时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

差异#3

如果 的右侧instanceof是绑定函数,则将其等同于其目标函数。

如果 b 是绑定函数:

  • a instanceof b会工作得很好。
  • b.prototype.isPrototypeOf(a)将导致TypeError(绑定函数没有prototype属性)。

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

结论

  • 如果您正在处理通过 建立的原型继承Object.create(),而不使用构造函数,则您可能应该使用该Object.prototype.isPrototypeOf()方法(实际上, 的用例instanceof受到更多限制,因为它instanceof期望其右侧参数是构造函数)。
  • 如果您正在处理构造函数,则使用instanceof运算符会稍微安全一些(您将能够涵盖绑定函数以及Object.prototype不在原型链中的情况Constructor.prototype)。
于 2019-01-04T16:32:34.617 回答
2

运算符优先级和真实性不同,因为一个是表达式,另一个是方法调用。需要强调的一点是,两者都遍历原型链,因此您不能假设匹配的原型和相关对象之间存在一对一的映射:

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

参考

于 2013-11-19T23:51:44.473 回答