Javascript,扩展 ES6 类 setter 将继承 getter

Posted

技术标签:

【中文标题】Javascript,扩展 ES6 类 setter 将继承 getter【英文标题】:Javascript, extending ES6 class setter will inheriting 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. 【参考方案1】:

这个限制是由于 JavaScript 如何在后台处理属性访问器。在 ECMAScript 5 中,您最终会得到一个原型链,其中包含一个用于 val 的 property 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。

以上是关于Javascript,扩展 ES6 类 setter 将继承 getter的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript ES6 - 数组扩展

es6简单介绍

JavaScript ES6 - 函数扩展

JavaScript ES6 - 函数扩展

如何在扩展类 javascript 中获取更新的对象数组

JavaScript ES6 - 对象扩展