5

instanceof操作员应该看原型,不是吗?为什么在对象的原型改变后它不改变它的答案?下面的例子:

// The .prototype of objects created with 'new MyKlass'
// is MyKlass.prototype
var MyKlass = function(name, age) {
  this.name = name;
  this.age = age;
}

var xx = new MyKlass('xx', 20);
console.log(xx instanceof MyKlass);      // true, OK

xx.prototype = new String('s');
console.log(xx instanceof MyKlass);      // also true, WHY???
4

3 回答 3

9

这种情况在 MDN 中有解释:

请注意,如果 instanceof 测试的值可以根据构造函数的原型属性的更改而更改,则无法通过更改对象原型来更改它,因为在标准 ECMAScript 中无法更改对象原型。然而,可以使用非标准的__proto__伪属性

这将记录 false :

xx.constructor.prototype = new String('s');
console.log(xx instanceof MyKlass);

简而言之,你不应该尝试改变 JavaScript 对象,它们的设计初衷不是可变的。我不知道您的用例是什么,但可能有更好的解决方案,无论是组合、内部状态还是其他。

于 2013-06-27T13:03:42.083 回答
3

它不看.prototype但 [[prototype]],或者在某些浏览器中可用的内容为.__proto__

xx.__proto__ = new String("s");
console.log(xx instanceof MyKlass); 
//false
console.log(xx instanceof String); 
//true

将属性分配.prototype给非函数实际上除了对任何正常属性的正常赋值之外没有任何效果。对于仅在函数用于instanceof检查或调用时才有效的函数new

于 2013-06-27T13:08:19.340 回答
3

instanceof 操作符应该看原型,不是吗?

是的,它确实。请参阅MDN 文档

为什么在对象的原型改变后它不改变它的答案?

var xx = new MyKlass('xx', 20);
xx.prototype = new String('s');

因为您没有更改xx对象的原型,而是给了它一个prototype属性。Object.getPrototypeOf(xx) === MyKlass.prototype仍然适用。见__proto__ VS。JavaScript 中的原型以获取详细信息。什么会起作用:

MyKlass.prototype = {}; // overwrite with a different object
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from the {}

或者

xx.__proto__ = String.prototype; // or something
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from MyKlass.prototype

请注意,写入内部 [[prototype]] via__proto__在 ES5 中是非标准的

于 2013-06-27T13:12:22.367 回答