如何在 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 + 1NaN。由new Animal 创建的实例 最初有一个count 属性,但Animal 本身没有,直到您调用increaseCountthisstatic 方法中指的是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 类中使用静态变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Python中定义静态变量

java 在调试的时候如何查看类中的静态变量值

如何在静态类中初始化final static变量?

如何访问在mapreduce中扩展reducer的静态内部类中的静态变量?

java的静态内部类中定义的变量是全局的么?

关于java静态变量取值的问题。