如何在 ES6 类中使用静态变量?
Posted
技术标签:
【中文标题】如何在 ES6 类中使用静态变量?【英文标题】:How do I use a static variable in ES6 class? 【发布时间】:2018-12-25 04:33:54 【问题描述】:我正在尝试在 es6 中使用静态变量。我想在Animal
类中声明一个静态变量count
并增加它。但是,我无法通过static count = 0;
声明静态变量,所以我尝试了另一种方式:
class Animal
constructor()
this.count = 0;
static increaseCount()
this.count += 1;
static getCount()
return this.count;
console.log(Animal.increaseCount()); // undefined
console.log(Animal.getCount()); // NaN
我希望 console.log(Animal.getCount());
是 1
,但它不起作用。
如何声明静态变量并通过调用方法对其进行修改?
【问题讨论】:
见***.com/questions/1535631/…undefined + 1 = NaN
【参考方案1】:
您的类没有静态变量(如果静态变量是指静态属性)。 getCount
返回 NaN
(在您调用 increaseCount
之后),因为 Animal
最初没有 count
属性。然后increaseCount
执行undefined + 1
即NaN
。由new Animal
创建的实例 最初有一个count
属性,但Animal
本身没有,直到您调用increaseCount
。 this
在static
方法中指的是Animal
类(构造函数)本身(如果您通过Animal.methodName(...)
调用它)。
你可以给Animal
一个count
属性:
Animal.count = 0;
现场示例:
class Animal
constructor()
static increaseCount()
this.count += 1;
static getCount()
return this.count;
Animal.count = 0;
Animal.increaseCount();
console.log(Animal.getCount());
Animal.increaseCount();
console.log(Animal.getCount());
使用 static class fields proposal(目前处于第 3 阶段),您可以在 Animal
中使用 static count = 0;
以声明方式执行此操作。 Live Example (Stack Snippets 的 Babel 配置似乎支持它):
class Animal
constructor()
static count = 0;
static increaseCount()
this.count += 1;
static getCount()
return this.count;
Animal.increaseCount();
console.log(Animal.getCount());
Animal.increaseCount();
console.log(Animal.getCount());
通过private static 提案(处于第 3 阶段并正在积极实施),您甚至可以将count
设为私有:
class Animal
constructor()
static #count = 0;
static increaseCount()
this.#count += 1;
static getCount()
return this.#count;
Animal.increaseCount();
console.log(Animal.getCount());
Animal.increaseCount();
console.log(Animal.getCount());
Stack Snippets 的 Babel 配置不支持,但您可以在 their REPL 中实时运行它。
旁注:如果有子类,在静态方法中使用this
来引用类(构造函数)有点棘手,因为例如,如果你有:
class Mammal extends Animal
然后
Mammal.increaseCount();
increaseCount
中的this
(它继承自Animal
)指的是Mammal
,而不是Animal
。
如果您想要这种行为,请使用this
。如果不这样做,请在那些 static
方法中使用 Animal
。
【讨论】:
在Animal
类中是否允许static count = 0;
?它导致SyntaxError: Unexpected token
。我正在将 Babel 与 Webpack 一起使用。
@Caesium133 - 正如我上面所说,这是 static class fields proposal 的一部分,目前处于流程的第 3 阶段(因此,它还没有在规范中,引擎只是现在才寻找添加它)。
怎么把increaseCount放到新Animal的构造函数中?归根结底,这难道不是人们通常想要在课堂上设置柜台的原因吗?看来你没有展示这种情况。 (我想count
应该是一个集合的属性,而不是实例类 - 将计数作为类的静态属性是一种“低预算”集合,嗯?
static count = 0;
这些天似乎在工作……我在做梦吗?但是,它与 Java 的 static 有很大的不同
@OhadR - 不,你不是在做梦。 :-) V8(在 Chrome、Node.js、Brave、Chromium、新 Edge 等中)和 SpiderMonkey(在 Firefox 75+ 中)都开始支持 static
公共字段。 Safari 仍在进行中。【参考方案2】:
要设置静态变量,请将其设置在对象 Animal 本身上。到目前为止,在 javascript 中,您不能像声明静态方法那样直接在类中声明静态属性。
class Animal
constructor()
static increaseCount()
this.count += 1;
static getCount()
return this.count;
Animal.count = 0;
console.log(Animal.increaseCount());
console.log(Animal.getCount());
【讨论】:
【参考方案3】:静态类端属性和原型数据属性必须在 ClassBody 声明之外定义。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
class Animal
static increaseCount()
Animal.count += 1;
static getCount()
return Animal.count;
Animal.count = 0;
Animal.increaseCount();
console.log(Animal.getCount()); // undefined
【讨论】:
没关系,但最后一行代码返回 1 ,不是未定义的。这可能会误导新手 今天不用再在外面申报了【参考方案4】:正如其他答案中提到的,this.count
指的是constructor
中的 instance 属性。为了初始化static属性,应该设置Animal.count
。
Class fields proposal 为 Animal.count = 0
提供语法糖,可用于转译器(Babel 等):
class Animal
static count = 0;
...
ES6 中的另一种选择是使用初始值,在这种情况下,Animal.count
初始值不需要显式设置,例如:
class Animal
static increaseCount()
this.count = this.getCount() + 1;
static getCount()
return this.count || 0;
在 JavaScript 类中不欢迎访问器方法 - 这就是 getter/setter 描述符的用途:
class Animal
static increaseCount()
this.count += 1;
static get count()
return this._count || 0;
static set count(v)
this._count = v;
仅静态类在 JavaScript 中被视为反模式,因为不使用特定于类的状态或其他特征。如果应该只有一个实例,则应该使用普通对象(除非有其他问题可以从class
中受益):
const animal =
increaseCount()
this.count += 1;
,
get count()
return this._count || 0;
,
set count(v)
this._count = v;
;
【讨论】:
但是你的getter和setter函数不是Accessor方法吗? 你的 getCount 不是 Accessor 方法吗? 带有 getter 和 setter 的 Animal 类返回 0:let b = new Animal; console.log(Animal.count);
我想说更有用的是,您的带有 get/set 的类应该在创建新实例时自增。如果 _count == 0,您的最终对象样式实际上不会返回 _count 的值。当 _count 实际上未定义时,它会返回 0。这是一个错误的结果。我认为这是一个错误。由于该对象需要在外部将 count 初始化为 0,因此它似乎与仅使用变量没有什么不同。行为与变量没有什么不同的对象是否被视为反模式?
@johnywhy 感谢您的注意,有一个错字,应该是 this.count 而不是 this._count in increaseCount 和除 get/set count 之外的其他成员。 get count() return this._count || 0
与 _count: 0, get count() return this._count
基本相同。我更喜欢|| 0
,因为它需要更少的字符来输入并且还修复了一些无效值,可以将set
中的this._count = +v || 0
更改为更好的值调节。如果它是反模式,则取决于具体情况。一个对象可以扩展并且更易于测试。如果需要,它的行为可以随时更改【参考方案5】:
你可以使用闭包来模拟静态变量
const Animal= (() =>
let count= 0;
class Animal
constructor()
static increaseCount()
count += 1;
static getCount()
return count;
return Animal;
)();
console.log(Animal.getCount());
Animal.increaseCount();
console.log(Animal.getCount());
【讨论】:
【参考方案6】:如果你想拥有增量 ID:
constructor()
super(template);
if (typeof MyClass.nextId == 'undefined')
MyClass.nextId = 0;
this._id = `$MyClass.nextId++`;
【讨论】:
【参考方案7】:您可以使用静态 getter 和 setter 模拟静态变量
export class MyClass
static get variable()
return this.foo;
static set variable(foo)
this.foo = foo;
并像这样使用它
MyClass.variable = 'bar';
console.log(MyClass.variable);
【讨论】:
以上是关于如何在 ES6 类中使用静态变量?的主要内容,如果未能解决你的问题,请参考以下文章