在ES6类中声明静态常量?

时间:2015-09-18 08:22:19

标签: javascript class constants ecmascript-6

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

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

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

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

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

15 个答案:

答案 0 :(得分:313)

以下是您可以做的一些事情:

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

export const constant1 = 33;

并在必要时从模块导入。或者,根据您的静态方法构思,您可以声明static get accessor

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

  static get constant1() {
    return constant1;
  }

  static get constant2() {
    return constant2;
  }
}

这样,你就不需要括号:

const one = Example.constant1;

Babel REPL Example

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

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;
}

但遗憾的是,此class property syntax仅适用于ES7提案,即便如此,也不允许向该媒体资源添加const

答案 1 :(得分:23)

我正在使用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-2

答案 2 :(得分:13)

this document中声明:

  

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

这意味着故意这样。

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

constructor(){
    this.key = value
}

答案 3 :(得分:10)

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

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

尝试更改类会给你一个软失败(不会抛出任何错误,它只会没有效果)。

答案 4 :(得分: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;
        //...
    }
}

答案 5 :(得分:4)

就像https://stackoverflow.com/users/2784136/rodrigo-botti所说,我认为你正在寻找Object.freeze()。这是一个具有不可变静态的类的示例:

class User {
  constructor(username, age) {
    if (age < User.minimumAge) {
      throw new Error('You are too young to be here!');
    }
    this.username = username;
    this.age = age;
    this.state = 'active';
  }
}

User.minimumAge = 16;
User.validStates = ['active', 'inactive', 'archived'];

deepFreeze(User);

function deepFreeze(value) {
  if (typeof value === 'object' && value !== null) {
    Object.freeze(value);
    Object.getOwnPropertyNames(value).forEach(property => {
      deepFreeze(value[property]);
    });
  }
  return value;
}

答案 6 :(得分:2)

您可以通过冻结类将“常量”设置为只读(不可变)。例如

class Foo {
    static BAR = "bat"; //public static read-only
}

Object.freeze(Foo); 

/*
Uncaught TypeError: Cannot assign to read only property 'BAR' of function 'class Foo {
    static BAR = "bat"; //public static read-only
}'
*/
Foo.BAR = "wut";

答案 7 :(得分:1)

您可以使用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);
  }
}

答案 8 :(得分:1)

我做到了。

class Circle
{
    constuctor(radius)
    {
        this.radius = radius;
    }
    static get PI()
    {
        return 3.14159;
    }
}

保护PI的值不被更改,因为它是从函数返回的值。您可以通过Circle.PI访问它。任何分配给它的尝试都可以简单地以类似于通过[]分配给字符串字符的方式放在地板上。

答案 9 :(得分:1)

我发现的最简洁的方法是使用 TypeScript - 参见 How to implement class constants?

class MyClass {
    static readonly CONST1: string = "one";
    static readonly CONST2: string = "two";
    static readonly CONST3: string = "three";
}

答案 10 :(得分:0)

这是你可以做的另一种方式

&#13;
&#13;
/*
one more way of declaring constants in a class,
Note - the constants have to be declared after the class is defined
*/
class Auto{
   //other methods
}
Auto.CONSTANT1 = "const1";
Auto.CONSTANT2 = "const2";

console.log(Auto.CONSTANT1)
console.log(Auto.CONSTANT2);
&#13;
&#13;
&#13;

注意 - 订单很重要,你不能拥有上面的常量

用法 的console.log(Auto.CONSTANT1);

答案 11 :(得分:0)

如果您愿意在函数和类语法之间进行混合和匹配,可以在类之后声明常量(常量被“提升”)。请注意,Visual Studio Code将难以自动设置混合语法的格式(尽管它可以工作)。

class MyClass {
    // ...

}
MyClass.prototype.consts = { 
    constant1:  33,
    constant2: 32
};
mc = new MyClass();
console.log(mc.consts.constant2);    

答案 12 :(得分:0)

您可以这样定义它:

class Foo {
  static MyConst = 200;

  myFunc() {
    const doubleConst = Foo.MyConst * 2;
  }
}

答案 13 :(得分:0)

您可以使用import * as语法。尽管不是类,但它们是真实的const变量。

Constants.js

export const factor = 3;
export const pi = 3.141592;

index.js

import * as Constants from 'Constants.js'
console.log( Constants.factor );

答案 14 :(得分:0)

加上其他答案,您需要导出班级以在其他班级中使用。这是它的打字稿版本。

//Constants.tsx
const DEBUG: boolean = true;

export class Constants {
  static get DEBUG(): boolean {
    return DEBUG;
  }
}

//Anotherclass.tsx
import { Constants } from "Constants";

if (Constants.DEBUG) {
  console.log("debug mode")
}