qué es6 enum javascript enums ecmascript-6 immutability symbols

qué - Enums en Javascript con ES6



qué es numeric enums typescript (10)

Estoy reconstruyendo un antiguo proyecto Java en Javascript, y me di cuenta de que no hay una buena manera de hacer enumeraciones en JS.

Lo mejor que se me ocurre es:

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

La const evita que los Colors se reasignen, y su congelación evita la mutación de las claves y los valores. Estoy usando símbolos para que Colors.RED no sea igual a 0 , ni nada más aparte de sí mismo.

¿Hay algún problema con esta formulación? ¿Hay una mejor manera?

(Sé que esta pregunta se repite un poco, pero todas las preguntas y respuestas anteriores son bastante antiguas y ES6 nos brinda algunas capacidades nuevas).

EDITAR:

Otra solución, que trata el problema de la serialización, pero creo que todavía tiene problemas de dominio:

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

Al utilizar referencias de objetos como valores, obtiene la misma prevención de colisiones que los símbolos.


¿Hay algún problema con esta formulación?

No veo ninguno

¿Hay una mejor manera?

Colapsaría las dos declaraciones en una:

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

Si no le gusta la repetitiva, como las llamadas repetidas de Symbol , por supuesto, también puede escribir una función auxiliar makeEnum que cree lo mismo a partir de una lista de nombres.


Como se mencionó anteriormente, también podría escribir una función auxiliar makeEnum() :

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

Úselo así:

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


Comprueba cómo TypeScript lo hace . Básicamente hacen lo siguiente:

const MAP = {}; MAP[MAP[1] = ''A''] = 1; MAP[MAP[2] = ''B''] = 2; MAP[''A''] // 1 MAP[1] // A

Usa símbolos, congela objetos, lo que quieras.


Este es mi enfoque personal.

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


Podrías usar ES6 Map

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


Puede consultar Enumify , una biblioteca muy buena y bien presentada para enumeraciones de ES6.


Si bien usar Symbol como el valor de enumeración funciona bien para casos de uso simples, puede ser útil otorgar propiedades a las enumeraciones. Esto se puede hacer usando un Object como el valor de enumeración que contiene las propiedades.

Por ejemplo, podemos dar a cada uno de los Colors un nombre y un valor hexadecimal:

/** * Enum for common colors. * @readonly * @enum {{name: string, hex: string}} */ const Colors = Object.freeze({ RED: { name: "red", hex: "#f00" }, BLUE: { name: "blue", hex: "#00f" }, GREEN: { name: "green", hex: "#0f0" } });

La inclusión de propiedades en la enumeración evita tener que escribir sentencias de switch (y posiblemente olvidar nuevos casos en las sentencias de cambio cuando se extiende una enumeración). El ejemplo también muestra las propiedades y tipos de enumeración documentados con la anotación de enumeración JSDoc .

La igualdad funciona como se esperaba con Colors.RED === Colors.RED es true y Colors.RED === Colors.BLUE es false .



Tal vez esta solución? :)

function createEnum (array) { return Object.freeze(array .reduce((obj, item) => { if (typeof item === ''string'') { obj[item] = Symbol(item) } return obj }, {})) }