ES6 类 - 更新静态属性

Posted

技术标签:

【中文标题】ES6 类 - 更新静态属性【英文标题】:ES6 Classes - Updating Static Properties 【发布时间】:2017-10-20 19:56:00 【问题描述】:

我正在尝试找出替代方法来将静态(或类)属性设置为 ES6 类,然后在创建类的新实例后更改它。

例如,假设我有一个名为Geo 的类,我需要一个名为all 的静态属性,它将为我提供Geo 类的所有实例的数组。

此版本有效:

class Geo 
  constructor(name)
    this.name = name;
    Geo.all.push(this);
  


Geo.all = [];

ruby = new Geo("Ruby");
rocks = new Geo("Rocks");
console.log(Geo.all.length); // => 2

我宁愿不要在类定义之外设置属性。我已经尝试了一些东西,但似乎无法在类中创建可以从构造函数更新的静态属性。

我还应该提到我需要能够在不使用 Babel 或类似工具的情况下在浏览器 (Chrome) 中执行此操作。

以下是我尝试过的一些示例:

class Geo 
  constructor(name)
    this.name = name;
    Geo.all.push(this);
  
  static get all() 
    return [];
  


ruby = new Geo("Ruby");
rocks = new Geo("Rocks");
console.log(Geo.all.length); // => 0 

还有一个

class Geo 
  constructor(name)
    this.name = name;
    Geo.all.push(this);
  

  static all = [];


ruby = new Geo("Ruby");
rocks = new Geo("Rocks");
console.log(Geo.all.length); // => error unexpected "="

【问题讨论】:

在 ES6 中没有其他方法可以做到这一点。 Geo.all = [] 有什么问题? 你不应该有一个全局的实例集合——这会导致内存泄漏和模块化(例如可测试性)问题 您可以在构造函数中执行Geo.all = (Geo.all || []).concat(this);。然而,类定义之外的静态初始化程序是解决此问题的“惯用”标准方法。它还保证Geo.all 的存在,甚至在创建第一个实例之前。 如果您想跟踪特定对象的所有实例,那么您可能不想将它们放入数组中,因为这可能会导致内存泄漏,因为这样做会迫使您的代码管理每个对象的内存(您必须手动将其从数组中删除,以便垃圾收集器释放它,这会扼杀垃圾收集的很多用处)。您可以将它们放在 weakMapweakSet 中,具体取决于您希望如何访问它们并且不会杀死垃圾收集。 【参考方案1】:

ES6 中没有 static all = [] 这样的东西。 instance 和 static 类字段目前是第 3 阶段提案,可以通过转译器使用,例如通天塔。 TypeScript 中已有的实现可能在某种程度上与这些提议不兼容,但 static all = []TSES.Next 中有效。

Geo.all = [];

是在 ES6 中执行此操作的有效且可取的方式。另一种方法是 getter/setter 对 - 或者只是只读属性的 getter:

class Geo 
  static get all() 
    if (!this._all)
      this._all = [];

    return this._all;
  

  constructor()  ... 

在静态属性中跟踪实例通常不能被认为是一种好的模式,并且会导致无法控制的内存消耗和泄漏(正如在 cmets 中提到的那样)。

【讨论】:

截至 2017 年 12 月,它现在是第 3 阶段提案:github.com/tc39/proposal-class-fields#field-declarations @t3__rry,从你的链接来看,它不是静态属性【参考方案2】:

这对我来说适用于静态属性。

  class NeoGeo 

    constructor() 

    

    static get topScore () 
      if (NeoGeo._topScore===undefined) 
        NeoGeo._topScore = 0; // set default here
      

      return NeoGeo._topScore;
    

    static set topScore (value) 
      NeoGeo._topScore = value;
    

  

还有你的例子:

  class NeoGeo 

    constructor() 
      NeoGeo.addInstance(this);
      console.log("instance count:" + NeoGeo.all.length);
    

    static get all () 

      if (NeoGeo._all===undefined) 
        NeoGeo._all = [];
      

      return NeoGeo._all;
    

    static set all (value) 
      NeoGeo._all = value;
    

    static addInstance(instance) 
      // add only if not already added
      if (NeoGeo.all.indexOf(instance)==-1) 
        NeoGeo.all.push(instance);
      
    
  

注意:在 getter 中,您还可以使用 in 关键字或 hasOwnProperty 关键字检查属性是否存在。

    static get topScore () 
      if (!("_topScore" in NeoGeo)) 
        NeoGeo._topScore = 0; // set default here
      

      return NeoGeo._topScore;
    

并使用hasOwnProperty

    static get topScore () 
      if (NeoGeo.hasOwnProperty("_topScore")==false) 
        NeoGeo._topScore = 0; // set default here
      

      return NeoGeo._topScore;
    

【讨论】:

【参考方案3】:

我最近遇到了创建静态类的类似问题。

我首先尝试使用常量类变量,但 Chrome 调试器抛出错误。 所以我定义了类变量“静态”,还有 getter 方法。

在 Chrome 中工作。

class TestClass 
  //static properties.
  static _prop1 = [ 'A', 'B', 'C'];
  static _prop2 = true;
  static _prop3 = 'some String';
  
  //constructor. Commented out because the class only has static elements.
  //constructor () 
  
  //Getters.
  static get prop1 () 
    return this._prop1;
  
  
  static get prop2 () 
    return this._prop2;
  
  
  static get prop3 () 
    return this._prop3;
  

【讨论】:

【参考方案4】:

正确添加 getter 的唯一方法是扩展类并使用该扩展类。

class Basic 
  get firstGetter() 
    return 'firstGetter'
  

class ExtendedClass extends Basic 
  get firstGetter() 
    return 'updatedFirstGetter'
  

【讨论】:

【参考方案5】:

将您的节点更新到版本 12 或更高版本,就是这样 ;)

【讨论】:

你可以使用静态字段属性 developer.mozilla.org/en-US/docs/Web/javascript/Reference/…

以上是关于ES6 类 - 更新静态属性的主要内容,如果未能解决你的问题,请参考以下文章

ES6 class(基本语法+方法)

ES6---class的静态方法静态属性和实例属性

Javascript es6覆盖静态属性

ES6 class -- Class 的方法

ES6 类

Es6 的类(class)