JavaScript - 构造函数原型的改变会影响实例化的对象吗?

问题描述 投票:0回答:1

如果我有一个带有已定义原型的函数(构造函数),可以这样说:

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
。有人可以帮我理解这个吗?

javascript function object prototype
1个回答
0
投票

我不确定

_prototype
是什么意思。你是说
.__proto__
吗?还是
.prototype
?这两者是不同的东西(
.__proto__
已被弃用,支持
Object.getPrototypeOf
Object.setPrototypeOf
,以及类似的
Reflect
方法)。

“改变原型”有几种不同的含义。

  1. 替换

    [[Prototype]]
    ,就像用
    Object.setPrototypeOf
    一样。除了对可读性可能产生的影响外,还有性能因素,MDN 的警告中对此进行了总结:

    警告:根据现代 JavaScript 引擎优化属性访问的本质,更改对象的

    [[Prototype]]
    目前在每个浏览器和 JavaScript 引擎中都是非常缓慢的操作。此外,更改继承的影响是微妙且广泛的,并且不仅限于在
    Object.setPrototypeOf(...)
    语句中花费的时间,还可能扩展到可以访问其
    [[Prototype]]
    已更改的任何对象的任何代码。您可以在 JavaScript 引擎基础知识:优化原型中阅读更多内容。

    由于此功能是语言的一部分,因此高性能(理想情况下)实现该功能仍然是引擎开发人员的负担。在引擎开发人员解决此问题之前,如果您担心性能,则应避免设置对象的

    [[Prototype]]
    。相反,使用
    [[Prototype]]
    创建一个具有所需
    Object.create()
    的新对象。

    通过替换或添加属性来修改内置或库对象的
  1. [[Prototype]]

    。不鼓励这样做主要是因为它不是面向未来的。例如,

    Array.prototype.find
    是一个非常有用的函数,它在2012年不存在。如果有人将它添加到数组原型中,那么它会很有用,但是当几年后实现时,任何人自行定义
    Array.prototype.find
    将会用效率较低的代码替换效率较高的代码。
    您可以防范它,并且仅在尚未定义的情况下替换该函数,但随后可能会出现不兼容性。当找不到匹配元素时,现在标准的 

    .find

    将返回

    undefined
    。如果您的 polyfill 返回
    null
    ,但您忽略内置
    .find
    (以防它存在),并且您的代码在
    null
    undefined
    上的行为不同,那么您就会遇到问题。
    
    通过定义或替换原型来修改您自己的对象的 

    [[Prototype]]
  2. 耸耸肩。

    这是你的代码。是的,对原型属性的任何更改都将反映在原型对象中,除非它们被原型对象上的属性所掩盖。

    
    
        
    

© www.soinside.com 2019 - 2024. All rights reserved.