function Rabbit() {}
Rabbit.prototype = {
eats: true
};
let rabbit = new Rabbit();
Rabbit.prototype = {};
alert( rabbit.eats ); // ?
我知道当编译器读取语句(rabbit.eat)时,它首先在对象中检查属性是否存在然后它在rabbit.__proto__
中查找属性的Rabbit.prototype。但是在这里我们分配Rabbit.prototype = {}那么为什么对象兔子仍然有吃财产?
答案 0 :(得分:2)
实例化Rabbit的原型,rabbit
,仍然是原始Rabbit.prototype
对象,其eats: true
。重新分配原型并不意味着解释器遍历每个实例化对象并更改原型。
如果您想更改现有对象的原型,可以使用setPrototypeOf,如下所示:
function Rabbit() {}
Rabbit.prototype = {
eats: true
};
let rabbit = new Rabbit();
Rabbit.prototype = {};
Object.setPrototypeOf(rabbit, Rabbit.prototype);
alert(rabbit.eats); // ?
可是:
警告:根据现代JavaScript引擎如何在每个浏览器和JavaScript引擎中优化属性访问,非常慢的操作,改变对象的[[Prototype]]。改变继承对性能的影响是微妙和遥远的,并不仅仅局限于在Object.setPrototypeOf(...)语句中花费的时间,而是可以扩展到任何可以访问[[Prototype]的任何对象的代码。 ]]已被改变。如果您关心性能,则应避免设置对象的[[Prototype]]。而是使用Object.create()创建一个具有所需[[Prototype]]的新对象。
或者,代替重新分配原型,您可以将原型变成空对象:
function Rabbit() {}
Rabbit.prototype = {
eats: true
};
let rabbit = new Rabbit();
// `for..in` will iterate over all properties, including inherited ones
// if you don't want that, iterate over Object.keys instead
for (const key in Rabbit.prototype) {
delete Rabbit.prototype[key];
}
console.log(rabbit.eats);
其他突变到rabbit
的原始原型也将改变您在 rabbit 上可以访问的内容,只要您不是重新分配类的原型(创建一个单独的未链接对象):
function Rabbit() {}
Rabbit.prototype = {
eats: true
};
let rabbit = new Rabbit();
// mutation, not reassignment
Rabbit.prototype.eats = 'foo';
console.log(rabbit.eats); // ?
答案 1 :(得分:0)
function Rabbit() {}
Rabbit.prototype = {
eats: true
};
let rabbit = new Rabbit();
Rabbit.prototype = {};
alert( rabbit.eats );
let rabbit2 = new Rabbit();
alert(rabbit2.eats); //This will now say undefined
您没有更改已经实例化的对象的原型。