2015-09-18 3 views
150

Я хочу реализовать константы в class, потому что здесь есть смысл найти их в коде.Объявление статических констант в классах ES6?

До сих пор я реализую следующий метод обхода со статическими методами:

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

Я знаю, что есть возможность возиться с прототипами, но многие рекомендуют против этого.

Есть ли лучший способ реализовать константы в классах ES6?

+4

Лично я просто использую прописные ВАРНАМЫ и говорю себе, чтобы не трогать их;) – twicejr

+1

@twicejr Я думаю, что это не одно и то же, для статических переменных можно получить доступ без первого экземпляра объекта этого класса? –

ответ

184

Вот несколько вещей, которые вы могли бы сделать:

экспортирования const из модуля. В зависимости от вашего варианта использования вы можете просто:

export const constant1 = 33; 

И импортируйте это из модуля там, где это необходимо. Или, основываясь на вашей статической идее метода, вы можете объявить staticget 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 к собственности.

+12

статичный получить, приятно ... очень приятно ... – JVerstry

+9

@JVerstry это сарказм? –

+0

есть ли подтверждение того, что статические свойства вычисляются один раз для таких вещей, или безопаснее использовать IIFE и добавлять свойство вручную в IIFE, чтобы избежать повторного построения возвращаемых значений. Я волнуюсь, что, если результат геттера действительно тяжелый, например, объект JSObject, состоящий из 100 000, тогда бедный геттер должен будет построить его каждый раз, когда будет вызван приемник. Его легко проверить с помощью performance.now/date diff, но он может быть реализован по-разному, его определенно проще внедрить геттеры в качестве литеральной оценки, а не расширенных решений, будь то постоянная или нет. – Dmitry

10

В this document говорится:

не

Существует (намеренно) нет прямого декларативного способа определения либо свойств данных прототипа (кроме методов) свойств класса или экземпляра свойства

Это означает, что это намеренно нравится.

Возможно, вы можете определить переменную в конструкторе?

constructor(){ 
    this.key = value 
} 
+1

Да, это может сработать. Кроме того, я хочу упомянуть, что конструктор вызывает, когда экземпляр создан, и для каждого экземпляра this.key будет не то же самое. Статический метод и свойства позволяют использовать их непосредственно из класса без создания экземпляра. Есть хорошие и слабые точки статических методов/свойств. –

8

Также можно использовать 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

+0

Я люблю 'Object.freeze()' для обеспечения неизменности и много использовал его в последнее время. Просто не забудьте применить его рекурсивно! – jeffwtribble

14

Я использую 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"] 
} 
+8

Проблема в том, что константа переназначается. Op не хочет, чтобы этот – CodingIntrigue

+0

узел 5.4.1 и давал синтаксис err – Boyang

+0

привет @Boyang у вас установлена ​​«stage-0» и в '.babelrc'? – borracciaBlu

3

Как 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; 
} 
2

Вот еще один способ, которым Вы можете сделать

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

+2

Они не являются неизменными, хотя –

Смежные вопросы