在ES6类中声明静态常量?

Jér*_*nge 272 javascript class constants ecmascript-6

我想在a中实现常量class,因为在代码中找到它们是有意义的.

到目前为止,我一直在使用静态方法实现以下解决方法:

class MyClass {
    static constant1() { return 33; }
    static constant2() { return 2; }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

我知道有可能摆弄原型,但许多人建议不要这样做.

有没有更好的方法在ES6类中实现常量?

Cod*_*gue 342

这里有一些你可以做的事情:

const模块导出a .根据您的使用情况,您可以:

export const constant1 = 33;
Run Code Online (Sandbox Code Playgroud)

并在必要时从模块导入.或者,基于静态方法的想法,您可以声明一个static get访问器:

const constant1 = 33,
      constant2 = 2;
class Example {

  static get constant1() {
    return constant1;
  }

  static get constant2() {
    return constant2;
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,你就不需要括号:

const one = Example.constant1;
Run Code Online (Sandbox Code Playgroud)

Babel REPL示例

然后,如你所说,因为a class只是函数的语法糖,你可以添加一个不可写的属性,如下所示:

class Example {
}
Object.defineProperty(Example, 'constant1', {
    value: 33,
    writable : false,
    enumerable : true,
    configurable : false
});
Example.constant1; // 33
Example.constant1 = 15; // TypeError
Run Code Online (Sandbox Code Playgroud)

如果我们可以做以下事情可能会很好:

class Example {
    static const constant1 = 33;
}
Run Code Online (Sandbox Code Playgroud)

但遗憾的是,此类属性语法仅在ES7提案中,即使这样也不允许添加const到属性.

  • 尽管上面的方法巧妙地将常量属性添加到类中,但该常量的实际值在类定义“ {}”的“外部”,这确实违反了封装的定义之一。我猜仅在类内部定义一个常量属性就足够了,在这种情况下无需获取。 (2认同)

bor*_*Blu 23

我正在使用babel,以下语法对我有用:

class MyClass {
    static constant1 = 33;
    static constant2 = {
       case1: 1,
       case2: 2,
    };
    // ...
}

MyClass.constant1 === 33
MyClass.constant2.case1 === 1
Run Code Online (Sandbox Code Playgroud)

请考虑您需要预设"stage-0".
要安装它:

npm install --save-dev babel-preset-stage-0

// in .babelrc
{
    "presets": ["stage-0"]
}
Run Code Online (Sandbox Code Playgroud)

更新:

目前使用 stage-3

  • 问题是常数是可重新分配的.Op不希望如此 (16认同)
  • 仅供参考,这是现在的babel`stage-2` (3认同)
  • 那些不是常数 (3认同)
  • @CodingIntrigue 在类上调用 `Object.freeze()` 会解决这个问题吗? (2认同)
  • @Antimony 我还没有测试过,但我想是的。问题是它适用于该类的所有属性。也是非静态的。 (2认同)

Ben*_*gan 22

class Whatever {
    static get MyConst() { return 10; }
}

let a = Whatever.MyConst;
Run Code Online (Sandbox Code Playgroud)

似乎为我工作.

  • @PirateApp 您可以在任何地方作为静态方法访问它,甚至可以从类的实例内部访问它。然而,由于它是静态的,你不能在 `Whatever` 实例中使用 `this.MyConst`,你总是必须这样写:`Whatever.MyConst` (4认同)
  • 如果你希望它看起来和表现得像一个常量,你可能还想定义相应的 setter,比如 `static set MyConst(value) { throw new Error('cannot redefineconst'); }`,以避免 @jave.web 提到的静默错误。 (3认同)
  • 我也这样做了,但它从根本上与“静态”的定义相冲突,因为返回的值不在实例之间共享。虽然很方便,但最终是一个糟糕的选择 (2认同)

Dev*_*ien 13

本文件中,它指出:

(故意)没有直接声明方式来定义原型数据属性(方法除外)类属性或实例属性

这意味着故意这样.

也许你可以在构造函数中定义一个变量?

constructor(){
    this.key = value
}
Run Code Online (Sandbox Code Playgroud)

  • 常量应该是不可变的。在构造期间分配给对象的属性将产生可以修改的属性。 (5认同)
  • 是的,这可以工作.另外,我想提一下,构造函数在创建实例时调用,对于每个实例,this.key都不一样.静态方法和属性允许我们直接从类中使用它们,而无需创建实例.静态方法/属性有优点和缺点. (2认同)

rod*_*tti 10

也可以Object.freeze在你的类(es6)/构造函数(es5)对象上使用它来使它不可变:

class MyConstants {}
MyConstants.staticValue = 3;
MyConstants.staticMethod = function() {
  return 4;
}
Object.freeze(MyConstants);
// after the freeze, any attempts of altering the MyConstants class will have no result
// (either trying to alter, add or delete a property)
MyConstants.staticValue === 3; // true
MyConstants.staticValue = 55; // will have no effect
MyConstants.staticValue === 3; // true

MyConstants.otherStaticValue = "other" // will have no effect
MyConstants.otherStaticValue === undefined // true

delete MyConstants.staticMethod // false
typeof(MyConstants.staticMethod) === "function" // true
Run Code Online (Sandbox Code Playgroud)

试图改变类将给你一个软失败(不会抛出任何错误,它将没有任何效果).

  • 对于我们这些来自其他语言的人来说,软故障是非常可怕的 - 只是适应这些工具对我们找不到错误的帮助,现在即使运行时也无济于事.(否则我喜欢你的解决方案.) (3认同)

TbW*_*321 8

您可以使用 ES6 类的一个奇怪功能创建一种在类上定义静态常量的方法。由于静态由其子类继承,因此您可以执行以下操作:

const withConsts = (map, BaseClass = Object) => {
  class ConstClass extends BaseClass { }
  Object.keys(map).forEach(key => {
    Object.defineProperty(ConstClass, key, {
      value: map[key],
      writable : false,
      enumerable : true,
      configurable : false
    });
  });
  return ConstClass;
};

class MyClass extends withConsts({ MY_CONST: 'this is defined' }) {
  foo() {
    console.log(MyClass.MY_CONST);
  }
}
Run Code Online (Sandbox Code Playgroud)


aRI*_*IEL 5

也许只是将您的所有常量都放在冻结的对象中?

class MyClass {

    constructor() {
        this.constants = Object.freeze({
            constant1: 33,
            constant2: 2,
        });
    }

    static get constant1() {
        return this.constants.constant1;
    }

    doThisAndThat() {
        //...
        let value = this.constants.constant2;
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 静态函数不能使用变量“this”。 (2认同)