在ES6类中声明静态常量?

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

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

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

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

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

357918 次浏览

这个文档中它声明:

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

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

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

constructor(){
this.key = value
}

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

模块. xml中导出const。根据你的用例,你可以:

export const constant1 = 33;

并在必要时从模块中导入。或者,基于你的静态方法思想,你可以声明一个static 获得访问器:

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


static get constant1() {
return constant1;
}


static get constant2() {
return constant2;
}
}

这样,你就不需要括号了:

const one = Example.constant1;

< a href = " https://babeljs.io/repl/ ?实验= true&评估= true&宽松= false&规范= false&代码= const % 20 constant1 % 20% 3 d % 2033% 2 c % 0 a % 20 constant2 % 20% 20% 20% 20% 20% 20% 3 d % 202% 3 b % 0 aclass % 20例7 b % 0 a % % 20% 20% 20% 0 20% % 20静态% 20得到% 20 constant1 7 b % 0 a %() % 20% 20% 20% 20% 20返回% 20 constant1 % 3 b % 0 7 d % 0 a % % 20% 20% 20% 20% 0 20% % 20静态% 20得到% 20 constant2 7 b % 0 a %() % 20% 20% 20% 20% 20返回% 20 constant2 % 3 b % 0 a % 20% 20% 7 d % 0 a % 7 d % 0 aconsole.log (Example.constant1 % 2 c % 20 example.constant2) % 3 b”rel = " noreferrer " >巴贝尔REPL示例< / >

然后,正如你所说,由于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;
}

但不幸的是,这个类属性语法只在ES7提案中,即使这样,它也不允许将const添加到属性中。

也可以在类(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

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

我使用的是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

更新通天塔7:

根据Babel 7 不支持舞台预设

要使用的Babel插件是@babel/plugin-proposal-class-properties

npm i --save-dev @babel/plugin-proposal-class-properties


{
"plugins": ["@babel/plugin-proposal-class-properties"]
}

注意:这个插件包含在@babel / preset-env

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

这里还有一种方法

/*
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);

注意-顺序很重要,你不能有上面的常量

使用

console.log(Auto.CONSTANT1);

您可以使用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);
}
}
class Whatever {
static get MyConst() { return 10; }
}


let a = Whatever.MyConst;

似乎对我有用。

也许把你所有的常量都放在一个冻结的对象里?

class MyClass {


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


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


doThisAndThat() {
//...
let value = this.constants.constant2;
//...
}
}

如果你喜欢混合和匹配函数和类的语法,你可以在类之后声明常量(常量被“提升”)。注意,Visual Studio Code将很难自动格式化混合语法(尽管它可以工作)。

class MyClass {
// ...


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

我做了这个。

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

PI的值被保护不被改变,因为它是一个函数返回的值。你可以通过Circle.PI访问它。任何对它的赋值尝试都被简单地丢弃,其方式类似于试图通过[]对字符串字符进行赋值。

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

通过冻结类,可以使“常量”为只读(不可变)。如。

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

加上其他答案,您需要导出类以在不同的类中使用。这是它的typescript版本。

//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")
}

我发现的最干净的方法是使用TypeScript -参见如何实现类常量?

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

给你!

const Status = Object.freeze(class Status {
static Disabled = 0
static Live = 1
})

如果试图将const/variable作为类的静态对象;尝试使用散列(#)来定义占位符,而不是使用函数来访问它。

class Region {
// initially empty, not accessible from outside
static #empty_region = null;


/*
Make it visible to the outside and unchangeable
[note] created on first call to getter.
*/


static EMPTY() {
if (!this.#empty_region)
this.#empty_region = new Region(0, 0, 0, 0);
return this.#empty_region;
}


#reg = {x0:0, y0:0, x1:0, y1:0};


constructor(x0, y0, x1, y1) {
this.setRegion(x0, y0, x1, y1);
}


// setters/getters
}

实现:

let someRegion = Region.EMPTY();


let anotherRegion = Region.EMPTY();

只需将变量声明为私有并使用get方法检索它们。

class MyClass {


#myConst = 'Something';


static #anotherConst = 'Something Else';


get myConst() {
return this.#myConst; // instance method
}


static get anotherConst() {
return MyClass.#anotherConst; // static method
}
}


let myClass = new MyClass();


console.log( myClass.myConst + ' is not ' + MyClass.anotherConst );

用户不能更改原始变量,您可以编写类来使用get方法而不是私有变量本身。