javascript - 为什么 getter 或 setter 在 JavaScript 中不能独立继承?
问题描述
考虑以下:
class Base {
_value;
constructor() {
this._value = 1;
}
get value() { return this._value; }
set value(v) { this._value = v; }
}
class Derived extends Base {
set value(v) {
// ...
super.value = v;
}
}
const d = new Derived();
d.value = 2;
console.log(d.value); // <-- undefined
我希望类的“getter”方法在 的Base
类中被“继承”,Derived
因此显示的值2
而不是undefined
。似乎“getter”或“setter”方法都不是独立继承的,而是被共同视为一个实体。从某种意义上说,如果重写的 setter 方法不存在,或者它与相应的 getter 耦合(具体在派生类中声明,而不是被继承),如下所示:
get value() { return super.value; }
那么,就不会有这样的问题了。
那么,为什么 getter 或 setter 不是独立继承的,因为它们应该解耦读取和设置字段的概念?
解决方案
JavaScript 的类继承使用原型链将子级Constructor.prototype
连接到父级Constructor.prototype
以进行委托。通常,super()
构造函数也被调用。这些步骤形成了单祖先父/子层次结构,并创建了 OO 设计中可用的最紧密耦合。
我建议你阅读一篇关于掌握 JavaScript 面试的非常好的文章:类和原型继承之间有什么区别?埃里克·埃利奥特 (Eric Elliott) 撰写。
更新
用于详细说明;这是预期的行为,因为您正在向Derived.prototype
. 当您使用get
or添加描述符时set
,实际上有一个使用该名称创建的函数,因此如果未设置,它将评估为未定义。它变得像一个自己的财产。
标准 ECMA-262
14.3.9运行时语义:PropertyDefinitionEvaluation
- MethodDefinition :
set
PropertyName ( PropertySetParameterList ) { FunctionBody }- 让propKey成为评估PropertyName的结果。 ReturnIfAbrupt ( propKey )。
- 如果此MethodDefinition的功能代码是严格模式代码,则让strict为真。否则让strict为false。
- 让scope为正在运行的执行上下文的LexicalEnvironment。
- 让formalParameterList成为生产形式FormalParameters:[空]
- 让闭包为FunctionCreate (Method, PropertySetParameterList , FunctionBody , scope , strict )。
- 执行MakeMethod(闭包,对象)。
- 执行SetFunctionName ( closure , propKey ,
"set"
)。- 令desc为 PropertyDescriptor{[[Set]]: closure , [[Enumerable]]: enumerable , [[Configurable]]: true }
- 返回DefinePropertyOrThrow ( object , propKey , desc )。
6.2.4.6 CompletePropertyDescriptor(描述)
当使用Property Descriptor Desc调用抽象操作 CompletePropertyDescriptor 时,将执行以下步骤:
- ReturnIfAbrupt (描述)。
- 断言:Desc是一个属性描述符
- 让like成为 Record{[[Value]]: undefined , [[Writable]]: false , [[Get]]: undefined , [[Set]]: undefined , [[Enumerable]]: false , [[Configurable]] :假}。
- 如果IsGenericDescriptor ( Desc ) 或IsDataDescriptor ( Desc ) 为真,则
- 一个。如果Desc没有 [[Value]] 字段,请将Desc .[[Value]] 设置为like .[[Value]]。
- 湾。如果Desc没有 [[Writable]] 字段,请将Desc .[[Writable]] 设置为like .[[Writable]]。
- 别的,
- 一个。如果Desc没有 [[Get]] 字段,请将Desc .[[Get]] 设置为like .[[Get]]。
- 湾。如果Desc没有 [[Set]] 字段,请将Desc .[[Set]] 设置为like .[[Set]]。
- 如果Desc没有 [[Enumerable]] 字段,请将Desc .[[Enumerable]] 设置为like .[[Enumerable]]。
- 如果Desc没有 [[Configurable]] 字段,请将Desc .[[Configurable]] 设置为like .[[Configurable]]。
- 返回描述。
还可以查看表 5 - 基本内部方法中的6.1.7.2对象内部方法和内部槽,尤其是和。GetOwnProperty
DefineOwnProperty
[[GetOwnProperty]] (propertyKey) → 未定义 | 属性描述符
返回此对象自己的属性的属性描述符,其键为propertyKey,如果不存在此类属性,则返回undefined 。
[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) → 布尔值
创建或更改自己的属性,其键为propertyKey,以具有由PropertyDescriptor描述的状态。如果该属性已成功创建/更新,则返回true ;如果无法创建或更新该属性,则返回false 。
推荐阅读
- android - 是否可以在线性布局内约束两个小部件?
- java - Java 8:使用另一个列表过滤对象内的列表
- ios - 当应用程序进入后台时,SwiftUI View 停止更新
- c++ - Visual Studio 不允许结构中的向量
- windows - 是否可以使用命令行标志打开无头和最大化的 Chrome?
- sql-server - SQL Server:如何避免以高并发对同一行进行多次更新
- typescript - 在某些目录中进行更改时防止重启 NestJS 服务器
- r - R - 在收集函数中使用列索引
- reactjs - 调度和设置状态后是否调用或更新渲染
- android - _TypeError(类型'列表
' 不是 'PlaceDetails' 类型的子类型)