javascript - 为什么实例化的对象即使在原型被重新分配给空对象后仍然具有原型的属性?
问题描述
function Rabbit() {}
Rabbit.prototype = {
eats: true
};
let rabbit = new Rabbit();
Rabbit.prototype = {};
alert( rabbit.eats ); // ?
据我所知,当编译器读取语句 (rabbit.eat) 时,它首先检查对象是否存在该属性,然后它会查看rabbit.__proto__
属性的 Rabbit.prototype。但是在这里我们分配 Rabbit.prototype = {} 那么为什么对象 rabbit 仍然具有 eat 属性?
解决方案
实例化 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); // ?
推荐阅读
- react-native - 捕获新视频时如何不捕获设备上运行的音频播放
- apache-spark - Pyspark 在返回 0 的双精度数上转换整数
- visual-studio-code - vscode如何让“打字屏”变大
- amazon-web-services - FFMpeg WebVTT hls 播放列表不同步
- python - Traceback(最近一次调用最后一次):文件“/var/www/html/tki.py”,_tkinter.TclError:没有显示名称
- r - 为什么 R 中的 HTML 函数实际上不会编写 HTML?
- json - 我如何将字段 1 值作为 gson 的整数变量?
- reactjs - 无法访问“此”
- c - 如何在 C 中处理不同的验证问题集?
- python - pip install scipy 的问题 - RuntimeError: Broken toolchain: cannot link a simple C program