如果我有一个带有已定义原型的函数(构造函数),可以这样说:
function Student(name) {
this.name = name;
}
Student.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
}
我使用该函数实例化和对象(据我所知,它应该在创建时将新创建的对象的属性
_prototype
设置为上面的原型对象,并将 constructor
属性设置为 Student
函数)。
const s1 = new Student('John');
s1.sayHello();
我确信调用
sayHello()
会起作用,但是,如果我像这样改变 Student
的原型会怎么样?
Student.prototype.sayGoodbye = function() {
console.log(`Goodbye, my name is ${this.name}`);
}
s1
可以打电话给sayGoodbye
吗?
我读到
_prototype
不应该改变,所以在这个逻辑中它应该抛出一个错误,但是,在 Chrome 的控制台面板和 node.js 项目中尝试它,它工作并且 s1 可以调用 sayGoodbye
。有人可以帮我理解这个吗?
我不确定
_prototype
是什么意思。你是说.__proto__
吗?还是.prototype
?这两者是不同的东西(.__proto__
已被弃用,支持Object.getPrototypeOf
和Object.setPrototypeOf
,以及类似的Reflect
方法)。
“改变原型”有几种不同的含义。
替换
[[Prototype]]
,就像用 Object.setPrototypeOf
一样。除了对可读性可能产生的影响外,还有性能因素,MDN 的警告中对此进行了总结:
警告:根据现代 JavaScript 引擎优化属性访问的本质,更改对象的
目前在每个浏览器和 JavaScript 引擎中都是非常缓慢的操作。此外,更改继承的影响是微妙且广泛的,并且不仅限于在[[Prototype]]
语句中花费的时间,还可能扩展到可以访问其Object.setPrototypeOf(...)
已更改的任何对象的任何代码。您可以在 JavaScript 引擎基础知识:优化原型中阅读更多内容。[[Prototype]]
由于此功能是语言的一部分,因此高性能(理想情况下)实现该功能仍然是引擎开发人员的负担。在引擎开发人员解决此问题之前,如果您担心性能,则应避免设置对象的
。相反,使用[[Prototype]]
创建一个具有所需[[Prototype]]
的新对象。Object.create()
[[Prototype]]
。不鼓励这样做主要是因为它不是面向未来的。例如,
Array.prototype.find
是一个非常有用的函数,它在2012年不存在。如果有人将它添加到数组原型中,那么它会很有用,但是当几年后实现时,任何人自行定义 Array.prototype.find
将会用效率较低的代码替换效率较高的代码。您可以防范它,并且仅在尚未定义的情况下替换该函数,但随后可能会出现不兼容性。当找不到匹配元素时,现在标准的 .find
将返回
undefined
。如果您的 polyfill 返回 null
,但您忽略内置 .find
(以防它存在),并且您的代码在 null
和 undefined
上的行为不同,那么您就会遇到问题。
通过定义或替换原型来修改您自己的对象的 [[Prototype]]
这是你的代码。是的,对原型属性的任何更改都将反映在原型对象中,除非它们被原型对象上的属性所掩盖。