ES6 클래스에서 정적 상수를 선언 하시겠습니까?


311

코드에서 상수 class를 찾는 것이 합리적이기 때문에에 상수를 구현하고 싶습니다 .

지금까지 정적 메소드를 사용하여 다음 해결 방법을 구현했습니다.

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

나는 프로토 타입으로 바이올린을 칠 가능성이 있다는 것을 알고 있지만 많은 사람들이 이것을 반대하는 것이 좋습니다.

ES6 클래스에서 상수를 구현하는 더 좋은 방법이 있습니까?


7
개인적으로 나는 단지 대문자 VARNAMES를 사용하고 그것들을 건드리지 말라고 자신을 말하십시오;)
twicejr

3
@twicejr 나는 이것이 동일하지 않다고 생각합니다. 정적 변수는 먼저 해당 클래스의 객체를 인스턴스화하지 않고 액세스 할 수 있습니까?
Lucas Morgan

답변:


385

수행 할 수있는 몇 가지 작업은 다음과 같습니다.

내보내기 const으로부터 모듈 . 사용 사례에 따라 다음을 수행 할 수 있습니다.

export const constant1 = 33;

필요한 경우 모듈에서 가져옵니다. 또는 정적 메소드 아이디어를 기반으로 static get 접근 자를 선언 할 수 있습니다 .

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

  static get constant1() {
    return constant1;
  }

  static get constant2() {
    return constant2;
  }
}

그렇게하면 괄호가 필요하지 않습니다.

const one = Example.constant1;

바벨 REPL 예

그런 다음 말했듯이 a 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속성 에 추가 할 수는 없습니다 .


정적 속성이 이와 같은 일에 대해 한 번 계산된다는 확인이 있거나 IIFE를 사용하고 IIFE에서 속성을 수동으로 추가하여 반환 값이 반복적으로 생성되는 것을 피하는 것이 더 안전합니까? getter의 결과가 100000 항목 JSObject와 같이 실제로 무겁다면 getter가 호출 될 때마다 가난한 getter가 구성해야한다고 걱정합니다. performance.now/date diff로 테스트하기는 쉽지만 다르게 구현 될 수 있지만 일정 여부에 관계없이 고급 의사 결정보다는 게터를 리터럴 평가로 구현하는 것이 훨씬 쉽습니다.
Dmitry

3
위의 클래스는 클래스에 상수 속성을 영리하게 추가하지만 상수의 실제 값은 클래스 정의 "{}"의 "외부"이며 이는 실제로 캡슐화 정의 중 하나를 위반합니다. 클래스의 "내부"에 상수 속성을 정의하는 것으로 충분하며이 경우에는 get이 필요하지 않습니다.
NoChance

1
@NoChance 좋은 지적. 그것은 단지 예시 일뿐입니다. 필요한 경우 getter 메소드가 값을 완전히 캡슐화하지 못한 이유는 없습니다.
CodingIntrigue

ES7 제안을 사용하기를 기대합니다. ES7 제안은 대부분의 OO 언어와 더 자연스럽고 동등한 것으로 보입니다.
Sangimed

상수 인스턴스 변수를 선언하고 싶은 것은 무엇입니까? 내가 할 수있는 this.defineProperty(this, 'constant1', {...})
Francesco Boi

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

let a = Whatever.MyConst;

나를 위해 일하는 것 같습니다.


클래스 내에서 일반적인 방법으로 액세스 할 수 있습니까?
PirateApp

3
@PirateApp 클래스의 인스턴스 내부에서도 정적 메서드로 어디서나 액세스 할 수 있습니다. 그러나 정적이기 때문에 인스턴스 this.MyConst내부에서 사용할 수 없으므로 Whatever항상 다음과 같이 작성해야합니다. Whatever.MyConst
TheDarkIn1978

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-3


21
문제는 상수를 재 할당 할 수 있다는 것입니다. Op는 그것을 원하지 않는다
CodingIntrigue

3
참고로,이 바벨에서 지금stage-2
bmaupin

3
그것들은 상수가 아닙니다
Dave L.

1
@CodingIntrigue Object.freeze()클래스를 호출 하면 문제가 해결됩니까?
안티몬

1
@Antimony 나는 그것을 테스트하지는 않았지만 그렇게 생각할 것입니다. 문제는 클래스의 모든 속성에 적용된다는 것입니다. 정적이 아닙니다.
CodingIntrigue

14

이 문서 에서는 다음과 같이 설명 합니다.

프로토 타입 데이터 속성 (메소드 이외의) 클래스 속성 또는 인스턴스 속성을 정의하기위한 (의도적으로) 직접적인 선언적 방법은 없습니다

이것은 의도적으로 이와 같다는 것을 의미합니다.

생성자에서 변수를 정의 할 수 있습니까?

constructor(){
    this.key = value
}

2
예, 이것이 가능합니다. 또한 인스턴스 생성시 생성자가 호출되며 각 인스턴스마다 this.key는 동일하지 않습니다. 정적 메서드와 속성을 사용하면 인스턴스를 만들지 않고도 클래스에서 직접 사용할 수 있습니다. 정적 메소드 / 속성에는 장점과 단점이 있습니다.
Kirill Gusyatin

1
상수는 불변이어야합니다. 구성하는 동안 객체의 속성에 할당하면 수정할 수있는 속성이 생성됩니다.
philraj 2016 년

11

사용하는 것도 가능하다 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

클래스를 변경하려고하면 소프트 실패가 발생합니다 (오류가 발생하지 않으며 단순히 효과가 없습니다).


3
이 소프트 실패는 다른 언어를 사용하는 사람들에게는 무섭습니다. 툴을 사용하여 오류를 찾는 데 큰 도움이되지 않는다는 아이디어에 적응하면 런타임조차도 도움이되지 않습니다. (그렇지 않으면 나는 당신의 해결책을 좋아합니다.)
Tom

나는 Object.freeze()불변성을 적용하는 것을 좋아 하고, 최근에 많이 사용하고 있습니다. 재귀 적으로 적용하는 것을 잊지 마십시오!
jeffwtribble

6

어쩌면 모든 상수를 얼어 붙은 물체에 넣었습니까?

class MyClass {

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

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

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

정적 함수는 변수 'this'를 사용할 수 없습니다.
PokerFace

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

1

여기에 당신이 할 수있는 또 다른 방법이 있습니다

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


5
그들은 비록 변경할 수 없습니다
존 하딩

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

1

클래스를 고정하여 "상수"를 읽기 전용 (불변)으로 만들 수 있습니다. 예 :

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

0

함수와 클래스 구문을 편안하게 혼합하고 일치시키는 경우 클래스 다음에 상수를 선언 할 수 있습니다 (상수는 '리프팅됩니다'). Visual Studio Code는 혼합 구문을 자동 형식화하는 데 어려움을 겪습니다 (작동하지만).

class MyClass {
    // ...

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


0

나는 이걸했다.

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

PI의 값은 함수에서 반환되는 값이므로 변경되지 않습니다. Circle.PI를 통해 액세스 할 수 있습니다. 할당하려는 모든 시도는 []를 통해 문자열 문자에 할당하려는 시도와 유사한 방식으로 바닥에 떨어집니다.


0

다음과 같이 정의 할 수 있습니다.

class Foo {
  static MyConst = 200;

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

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 );
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.