Javascript中isPrototypeOf和instanceof有什么区别?

发布于 2024-08-25 03:36:04 字数 434 浏览 6 评论 0原文

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

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

然后我这样做(例如)

[].instanceOf( Array )

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

[] instanceof Array

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

a instanceof b ALWAYS 是否与 b.prototype.isPrototypeOf(a) 相同?

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) ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谜兔 2024-09-01 03:36:04

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

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

instanceof 是一个运算符 它需要两个操作数,一个对象和一个 构造函数,它将测试传递的函数 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

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, e.g. 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
夜巴黎 2024-09-01 03:36:04

a instanceof b 是否始终与 b.prototype.isPrototypeOf(a) 相同?

不,a instanceof b 的行为并不总是与 b.prototype.isPrototypeOf(a) 相同。

CMS的回答指出它们的不同之处在于它们是什么(一个是运算符,另一个是可用的内置方法在 Object.prototype 对象上)。这是正确的,但是也有一些特殊情况,在 b.prototype.isPrototypeOf(a)a instanceof b 会导致 TypeError > 会工作得很好,反之亦然。

区别#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) 将导致 类型错误
  • 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的原型链中)。

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).
眸中客 2024-09-01 03:36:04

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

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

参考

Operator precedence and truthiness differ since one is an expression and the other is a method call. One thing to emphasize is that both traverse the prototype chain, 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文