【问题标题】:Why can't I substitute a class's prototype with another class's?为什么我不能用另一个类的原型替换一个类的原型?
【发布时间】:2019-01-30 06:43:25
【问题描述】:

给定两个类,我想将一个类的方法提供给另一个类:

class a {}
class b {say() {console.log('hello')}}
var foo = new a();

这是怎么回事:

a.prototype.say = b.prototype.say;
foo.say();    //'hello'

但这不是吗?

a.prototype = b.prototype;
foo.say();    //foo.say is not a function

要清楚,我不是在问如何将一个类的方法提供给另一个,而是为什么原型的行为是这样的。

额外问题:在类块中定义方法和通过直接将其分配给原型来定义它有什么区别?

【问题讨论】:

    标签: javascript javascript-objects


    【解决方案1】:

    原因是类上的prototype 是不可写、不可配置的属性:

    class a {}
    class b {say() {console.log('hello')}}
    
    console.log(Object.getOwnPropertyDescriptor(a,'prototype'))

    不可写意味着您无法重新分配属性prototype,不可配置意味着您无法更改属性以创建writable: true 或删除该属性。

    结果是这个没有效果:

    class a {}
    class b {say() {console.log('hello')}}
    
    a.prototype = b.prototype;
    console.log(a.prototype === b.prototype)

    但不可写仅意味着您不能更改与属性a.prototype 关联的值——它总是指向同一个对象——这并不意味着你不能向该对象添加属性。这就是为什么您仍然可以添加a.prototype.say

    【讨论】:

    • 另外值得补充的是,这与声明 function a(){}function b(){} 略有不同,其中 a.prototype = b.prototype 实际上会更改原型属性。
    • @zzzzBov 这很有趣。 javascript“类”和函数之间还有其他区别吗?即使它们在内部应该是一样的。
    • @leinaD_natipaC,它们不应该是同一回事。 class 是用于创建构造函数和原型的一系列常见最佳实践的语法糖,因此它本质上添加了许多可以复制的样板文件,如果您选择这样做的话。
    • @zzzzBov 这是我见过的对 js 类与函数的最佳描述。我搜索了类与函数,found a decent stackoverflow answer。似乎确实这些差异主要是一些样板文件以及您在类定义中可以做和不能做的事情。如果我将a 声明为一个函数并且然后 做了a.prototype = b.prototype,我是否可以期望a 的行为与b 完全一样,除了具有可重新分配的原型?
    • @leinaD_natipaC 简单地将原型从b 分配给a 不会使函数a 做与b 相同的事情。 ab 在调用时仍然是完全不同的函数,具有不同的行为——换句话说,a()b() 可能会做完全不同的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 2022-08-18
    • 1970-01-01
    相关资源
    最近更新 更多