Перечисления в Javascript с ES6

я перестраиваю старый проект Java в Javascript и понял, что нет хорошего способа сделать перечисления в JS.

лучшее, что я могу придумать-это:

const Colors = {
    RED: Symbol("red"),
    BLUE: Symbol("blue"),
    GREEN: Symbol("green")
};
Object.freeze(Colors);

на const держит Colors от переназначения и замораживания предотвращает мутацию ключей и значений. Я использую символы, так что Colors.RED не равно 0, или что-нибудь еще, кроме себя.

есть ли проблема с этой формулировкой? Есть лучше способ?


(я знаю, что этот вопрос немного повторяется, но все предыдущий Q / As довольно старые, и ES6 дает нам некоторые новые возможности.)


EDIT:

другое решение, которое касается проблемы сериализации, но я считаю, что все еще имеет проблемы с областью:

const enumValue = (name) => Object.freeze({toString: () => name});

const Colors = Object.freeze({
    RED: enumValue("Colors.RED"),
    BLUE: enumValue("Colors.BLUE"),
    GREEN: enumValue("Colors.GREEN")
});

используя ссылки на объекты в качестве значений, вы получаете то же предотвращение столкновений, что и символы.

8 ответов


есть ли проблема с этой формулировкой?

Я ничего не вижу.

есть ли лучший способ?

Я бы свернул два утверждения в одно:

const Colors = Object.freeze({
    RED:   Symbol("red"),
    BLUE:  Symbol("blue"),
    GREEN: Symbol("green")
});

Если вам не нравится шаблон, как повторяется Symbol вызовы, вы можете, конечно, также написать вспомогательную функцию makeEnum что создает то же самое из списка имен.


также проверить Enumify, очень хорошая и хорошо показанная библиотека для перечислений ES6.

надеюсь, это поможет кто-то.

с уважением,

Эммануэль


как упоминалось выше, вы также можете написать makeEnum() вспомогательную функцию:

function makeEnum(arr){
    let obj = {};
    for (let val of arr){
        obj[val] = Symbol(val);
    }
    return Object.freeze(obj);
}

используйте его так:

const Colors = makeEnum(["red","green","blue"]);
let startColor = Colors.red; 
console.log(startColor); // Symbol(red)

if(startColor == Colors.red){
    console.log("Do red things");
}else{
    console.log("Do non-red things");
}

Регистрация как TypeScript делает это. В основном они делают следующее:

const MAP = {};

MAP[MAP[1] = 'A'] = 1;
MAP[MAP[2] = 'B'] = 2;

MAP['A'] // 1
MAP[1] // A

используйте символы, заморозить объект, все, что вы хотите.


Если вам не нужен чисто ES6 и может использовать Typescript, он имеет хороший enum:

https://www.typescriptlang.org/docs/handbook/enums.html


вы также можете использовать пакет ES6-enum (https://www.npmjs.com/package/es6-enum). Он очень прост в использовании. См. пример ниже


вы можете использовать ES6 Map

const colors = new Map([
  ['RED', 'red'],
  ['BLUE', 'blue'],
  ['GREEN', 'green']
]);

console.log(colors.get('RED'));

Это мой личный подход.

class ColorType {
    static get RED () {
        return "red";
    }

    static get GREEN () {
        return "green";
    }

    static get BLUE () {
        return "blue";
    }
}

// Use case.
const color = Color.create(ColorType.RED);