【问题标题】:Javascript, extending ES6 class setter will inheriting getterJavascript,扩展 ES6 类 setter 将继承 getter
【发布时间】:2019-05-04 05:06:43
【问题描述】:

在 Javascript 中,带有以下插图代码:

class Base {
   constructor() {  this._val = 1   }
   get val()     { return this._val }
}

class Xtnd extends Base {
   set val(v)    { this._val = v }
}

let x = new Xtnd();
x.val = 5;
console.log(x.val);  // prints 'undefined'

实例x 不会从Base 类继承get val()...。事实上,Javascript 将在 setter 存在的情况下不存在 getter 视为未定义。

我有一种情况,我有很多类都有完全相同的 getter 集,但 setter 是唯一的。目前,我只是在每个类中复制 getter,但我正在重构并希望消除冗余代码。

有没有办法告诉 JS 让 getter 远离基类,或者有没有人有一个优雅的解决方案来解决这个问题?

【问题讨论】:

  • 供以后参考,这个问题与redundancy标签无关,它指的是故意复制代码以使关键部分更健壮。我很确定您打算使用boilerplate,它指的是看似不必要的代码重复。
  • "我有很多类都具有完全相同的 getter 集但唯一的 setter。" - 你真的需要继承吗?如果您只想避免重复,那么 JS 还有很多其他共享代码的方式。
  • "有没有办法告诉 JS 将 getter 保留在基类中" - No, it's by design.

标签: javascript extend es6-class boilerplate


【解决方案1】:

这个限制是由于 JavaScript 如何在后台处理属性访问器。在 ECMAScript 5 中,您最终会得到一个原型链,其中包含一个用于 valproperty descriptor 以及一个由您的类定义的 get 方法,以及一个未定义的 set 方法。

在您的Xtnd 类中,您有另一个val 的属性描述符,它隐藏了基类val 的整个属性描述符,其中包含一个由该类定义的set 方法和一个get 方法,即未定义。

为了将 getter 转发到基类实现,不幸的是,您需要在每个子类中使用一些样板,但您至少不必复制实现本身:

class Base {
   constructor() {  this._val = 1   }
   get val()     { return this._val }
}

class Xtnd extends Base {
   get val()     { return super.val }
   set val(v)    { this._val = v }
}

let x = new Xtnd();
x.val = 5;
console.log(x.val);  // prints '5'

【讨论】:

  • 这个半令人满意的解决方案有效。谢谢。 ...但对更优雅的解决方案抱有希望。
  • @codechimp 你在使用转译器吗?如果是这样,我可以使用类装饰器和/或方法装饰器添加另一个解决方案,将属性访问器转发到基类。这听起来像是对您有益的事情吗?
  • Transpilier 是我想到的一种解决方案,但我拒绝使用它。我理解它的价值,但我想保留这个代码库纯香草 JS。
猜你喜欢
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 2020-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多