在 ES6 类中声明静态常量?

IT技术 javascript class constants ecmascript-6
2021-02-06 04:47:03

我想在 a 中实现常量class,因为在代码中定位它们是有意义的。

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

class MyClass {
    static constant1() { return 33; }
    static constant2() { return 2; }
    // ...
}

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

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

6个回答

您可以执行以下操作:

constmodule中导出 a 根据您的用例,您可以:

export const constant1 = 33;

并在必要时从module中导入它。或者,基于您的静态方法想法,您可以声明一个static get 访问器

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

  static get constant1() {
    return constant1;
  }

  static get constant2() {
    return constant2;
  }
}

这样,您就不需要括号:

const one = Example.constant1;

Babel REPL 示例

然后,正如你所说,由于 aclass只是一个函数的语法糖,你可以像这样添加一个不可写的属性:

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

如果我们可以做这样的事情可能会很好:

class Example {
    static const constant1 = 33;
}

但不幸的是,此类属性语法仅在 ES7 提案中,即使如此,它也不允许添加const到属性中。

@NoChance 好点。那只是说明性的。如果需要,getter 方法没有理由不能完全封装该值。
2021-03-13 04:47:03
虽然上面巧妙地为类添加了一个常量属性,但常量的实际值在类定义“{}”的“外部”,这确实违反了封装的定义之一。我想在类“内部”定义一个常量属性就足够了,在这种情况下不需要 get 。
2021-03-16 04:47:03
期待使用 ES7 提案,因为在我看来它更自然,与大多数 OO 语言相当。
2021-03-21 04:47:03
是否有任何确认静态属性为这样的事情计算一次,或者使用 IIFE 并在 IIFE 中手动添加属性以避免重复构造返回值是否更安全。我担心如果getter 的结果真的很重,比如一个100000 条目的JSObject,那么可怜的getter 将不得不在每次调用getter 时构造它。它很容易通过 performance.now/date diff 进行测试,但它可能以不同的方式实现,将 getter 实现为文字评估肯定更容易,而不是无论其是否恒定的高级决策。
2021-03-26 04:47:03
super关键字是多一点点的语法糖
2021-04-02 04:47:03
class Whatever {
    static get MyConst() { return 10; }
}

let a = Whatever.MyConst;

似乎对我有用。

@PirateApp 您可以在任何地方作为静态方法访问它,甚至可以从类的实例内部访问它。然而,由于它是静态的,你不能this.MyConstWhatever实例内部使用,你总是必须这样写: Whatever.MyConst
2021-03-18 04:47:03
或 this.constructor.MyConst
2021-03-22 04:47:03
静态吸气剂可能是目前最干净的解决方案。
2021-03-24 04:47:03
我也这样做了,但它从根本上与“静态”的定义相冲突,因为返回值在实例之间不共享。这很方便,但最终是一个糟糕的选择
2021-03-25 04:47:03
这是否可以在类中以正常方法访问?
2021-04-11 04:47:03

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

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

MyClass.constant1 === 33
MyClass.constant2.case1 === 1

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

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

// in .babelrc
{
    "presets": ["stage-0"]
}

更新:

目前使用 stage-3

仅供参考,这现在在 babel 中 stage-2
2021-03-19 04:47:03
这些不是常数
2021-03-22 04:47:03
问题是常量是可重新分配的。欧普不想那样
2021-03-28 04:47:03
@Antimony 我还没有测试过,但我会这么认为。问题是它适用于类的所有属性。非静电也。
2021-04-04 04:47:03
@CodingIntrigue 会Object.freeze()在课堂上打电话解决这个问题吗?
2021-04-12 04:47:03

这份文件中,它指出:

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

这意味着它是故意这样的。

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

constructor(){
    this.key = value
}
常量应该是不可变的。在构造期间分配给对象上的属性将产生可以修改的属性。
2021-03-27 04:47:03
是的,这可以工作。另外,我想提一下,该构造函数在实例创建时调用,并且对于每个实例 this.key 都不相同。静态方法和属性允许我们直接从类中使用它们,而无需创建实例。静态方法/属性有优点和缺点。
2021-04-03 04:47:03

也可以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

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

我喜欢Object.freeze()强制执行不变性,并且最近一直在使用它。只是不要忘记递归应用它!
2021-03-27 04:47:03
对于我们这些来自其他语言的人来说,这种软失败是非常可怕的——只是适应了这些工具对我们发现错误没有多大帮助的想法,现在甚至运行时也无济于事。(否则我喜欢你的解决方案。)
2021-04-08 04:47:03