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
的存在,甚至在创建第一个实例之前。
如果您想跟踪特定对象的所有实例,那么您可能不想将它们放入数组中,因为这可能会导致内存泄漏,因为这样做会迫使您的代码管理每个对象的内存(您必须手动将其从数组中删除,以便垃圾收集器释放它,这会扼杀垃圾收集的很多用处)。您可以将它们放在 weakMap
或 weakSet
中,具体取决于您希望如何访问它们并且不会杀死垃圾收集。
【参考方案1】:
ES6 中没有 static all = []
这样的东西。 instance 和 static 类字段目前是第 3 阶段提案,可以通过转译器使用,例如通天塔。 TypeScript 中已有的实现可能在某种程度上与这些提议不兼容,但 static all = []
在 TS 和 ES.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 类 - 更新静态属性的主要内容,如果未能解决你的问题,请参考以下文章