javascript - 为什么 getter 或 setter 在 JavaScript 中不能独立继承?

标签 javascript oop inheritance getter-setter

考虑以下:

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


我期待 Base 的“getter”方法在 Derived 的类中“继承”的类,因此显示 2 的值而不是 undefined .似乎“getter”或“setter”方法都不是独立继承的,而是被共同视为一个实体。从某种意义上说,如果重写的 setter 方法不存在,或者它与相应的 getter 耦合(具体在派生类中声明,而不是被继承),如下所示:
get value() { return super.value; }

那么,就不会有这样的问题了。

那么,为什么 getter 或 setter 不是独立继承的,因为它们应该解耦读取和设置字段的概念?

最佳答案

JavaScript 的类继承使用原型(prototype)链来连接子 Constructor.prototype给家长Constructor.prototype为代表团。通常,super()构造函数也被调用。这些步骤形成了单祖先父/子层次结构,并创建了 OO 设计中可用的最紧密耦合。

我建议你阅读一篇关于 Master the JavaScript Interview: What’s the Difference Between Class & Prototypal Inheritance? 的非常好的文章埃里克·埃利奥特 (Eric Elliott) 撰写。

更新

用于详细说明;这是预期的行为,因为您正在向 Derived.prototype 添加新描述符.当您使用 get 添加描述符时或 set ,实际上有一个使用该名称创建的函数,因此如果未设置,它将评估为未定义。它变得像一个自己的属性(property)。

Standard ECMA-262

14.3.9 Runtime Semantics: PropertyDefinitionEvaluation

  1. MethodDefinition : set PropertyName ( PropertySetParameterList ) { FunctionBody }
  2. Let propKey be the result of evaluating PropertyName. ReturnIfAbrupt(propKey).
  3. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false.
  4. Let scope be the running execution context’s LexicalEnvironment.
  5. Let formalParameterList be the production FormalParameters : [empty]
  6. Let closure be FunctionCreate(Method, PropertySetParameterList, FunctionBody, scope, strict).
  7. Perform MakeMethod(closure, object).
  8. Perform SetFunctionName(closure, propKey, "set").
  9. Let desc be the PropertyDescriptor{[[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true}
  10. Return DefinePropertyOrThrow(object, propKey, desc).

6.2.4.6 CompletePropertyDescriptor ( Desc )

When the abstract operation CompletePropertyDescriptor is called with Property Descriptor Desc the following steps are taken:

  1. ReturnIfAbrupt(Desc).
  2. Assert: Desc is a Property Descriptor
  3. Let like be Record{[[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false}.
  4. If either IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then
    • a. If Desc does not have a [[Value]] field, set Desc.[[Value]] to like.[[Value]].
    • b. If Desc does not have a [[Writable]] field, set Desc.[[Writable]] to like.[[Writable]].
  5. Else,
    • a. If Desc does not have a [[Get]] field, set Desc.[[Get]] to like.[[Get]].
    • b. If Desc does not have a [[Set]] field, set Desc.[[Set]] to like.[[Set]].
  6. If Desc does not have an [[Enumerable]] field, set Desc.[[Enumerable]] to like.[[Enumerable]].
  7. If Desc does not have a [[Configurable]] field, set Desc.[[Configurable]] to like.[[Configurable]].
  8. Return Desc.


也看看6.1.7.2 Object Internal Methods and Internal SlotsTable 5 - Essential Internal Methods尤其是 GetOwnPropertyDefineOwnProperty .

[[GetOwnProperty]] (propertyKey) → Undefined | Property Descriptor

Return a Property Descriptor for the own property of this object whose key is propertyKey, or undefined if no such property exists.

[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) → Boolean

Create or alter the own property, whose key is propertyKey, to have the state described by PropertyDescriptor. Return true if that property was successfully created/updated or false if the property could not be created or updated.

关于javascript - 为什么 getter 或 setter 在 JavaScript 中不能独立继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60899900/

相关文章:

javascript - 将带时间的长日期转换为 mm-dd-yyyy hh :mm AM/PM

oop - UML 箭头的解释

c# - 如果派生类没有参数化构造函数,如何从派生类调用基类的参数化构造函数?

c# - 需要将信息保存在对象中的 C# 类方法

javascript - 为什么 JavaScript 使用原型(prototype)继承来实现?

c++ - 访问存储在 vector 中的指针内的字符串时崩溃

javascript - jquery 使用序列化比较元素

javascript - X-Editable 更改后 Knockout Subscribe 不触发

C++:对用户隐藏类构造

javascript - 无法将值发布到具有隐藏输入的下一个 HTML 文档