为什么在原型改变后,instanceof仍然说真实?

时间:2013-06-27 13:01:55

标签: javascript oop prototype

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

3 个答案:

答案 0 :(得分:9)

本案例解释为in the MDN

  

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

这会记录错误:

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

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

答案 1 :(得分:3)

它不是.prototype而是[[原型]],或某些浏览器中可用的.__proto__

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

.prototype属性分配给非函数除了正常分配任何普通属性外没有任何效果。对于仅在instanceof检查中使用该函数或使用new调用该函数时才有效的函数。

答案 2 :(得分:3)

  

instanceof运算符应该查看原型,不是吗?

是的,确实如此。请参阅MDN docs

  

为什么在对象的原型发生变化后它没有改变答案?

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

因为您没有更改xx对象的原型,但给它一个prototype属性。 Object.getPrototypeOf(xx) === MyKlass.prototype仍适用。有关详细信息,请参阅__proto__ VS. prototype in 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

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