Je reconstruis un ancien projet Java en Javascript et je me suis rendu compte qu'il n'y a pas de bon moyen de faire des énumérations dans JS.
Le mieux que je puisse trouver est:
const Colors = {
RED: Symbol("red"),
BLUE: Symbol("blue"),
GREEN: Symbol("green")
};
Object.freeze(Colors);
Le const
conserve Colors
d'être réaffecté et le gel empêche la mutation des clés et des valeurs. J'utilise des symboles pour que ce Colors.RED
ne soit pas égal à 0
, ou quoi que ce soit d'autre que lui-même.
Y a-t-il un problème avec cette formulation? Y a-t-il un meilleur moyen?
(Je sais que cette question est un peu répétée, mais tous les précédents Q / As sont assez anciens et ES6 nous donne de nouvelles capacités.)
ÉDITER:
Une autre solution, qui traite du problème de sérialisation, mais je crois que des problèmes de domaine persistent:
const enumValue = (name) => Object.freeze({toString: () => name});
const Colors = Object.freeze({
RED: enumValue("Colors.RED"),
BLUE: enumValue("Colors.BLUE"),
GREEN: enumValue("Colors.GREEN")
});
En utilisant des références d'objet comme valeurs, vous obtenez le même évitement de collision que Symbols.
la source
JSON.stringify()
. Impossible de sérialiser / désérialiserSymbol
.Réponses:
Je n'en vois pas.
Je réduirais les deux déclarations en une seule:
Si vous n'aimez pas le passe-partout, comme les
Symbol
appels répétés , vous pouvez bien sûr également écrire une fonction d'assistancemakeEnum
qui crée la même chose à partir d'une liste de noms.la source
Symbol.for
n'a pas de problèmes inter-royaumes, mais il a le problème de collision habituel avec un espace de noms vraiment global .enum => ({[Colors.RED]: "bright red", [Colors.BLUE]: "deep blue", [Colors.GREEN]: "grass green"}[enum])
).Bien que l'utilisation
Symbol
de la valeur enum fonctionne bien pour des cas d'utilisation simples, il peut être pratique de donner des propriétés aux énumérations. Cela peut être fait en utilisant uneObject
comme valeur d'énumération contenant les propriétés.Par exemple, nous pouvons donner à chacun des
Colors
un nom et une valeur hexadécimale:Inclure des propriétés dans l'énumération évite d'avoir à écrire des
switch
instructions (et éventuellement d'oublier de nouveaux cas dans les instructions switch lorsqu'une énumération est étendue). L'exemple montre également les propriétés et types d'énumération documentés avec l' annotation d'énumération JSDoc .L'égalité fonctionne comme prévu avec l'
Colors.RED === Colors.RED
êtretrue
et l'Colors.RED === Colors.BLUE
êtrefalse
.la source
Comme mentionné ci-dessus, vous pouvez également écrire une
makeEnum()
fonction d'assistance:Utilisez-le comme ceci:
la source
const makeEnum = (...lst) => Object.freeze(Object.assign({}, ...lst.map(k => ({[k]: Symbol(k)}))));
Ensuite, utilisez-le commeconst colors = makeEnum("Red", "Green", "Blue")
C'est ma démarche personnelle.
la source
Vérifiez comment TypeScript le fait . Fondamentalement, ils font ce qui suit:
Utilisez des symboles, figer un objet, tout ce que vous voulez.
la source
MAP[MAP[1] = 'A'] = 1;
place deMAP[1] = 'A'; MAP['A'] = 1;
. J'ai toujours entendu dire qu'utiliser un devoir comme expression était un mauvais style. En outre, quel avantage retirez-vous des affectations en miroir?MAP[MAP[1] = 'A'] = 1;
.x
est une valeur Enum valide en faisantEnum[Enum[x]] === x
. Cela ne résout aucun de mes problèmes d'origine, mais pourrait être utile et ne casse rien.Si vous n'avez pas besoin d' ES6 pur et que vous pouvez utiliser Typescript, il a un joli
enum
:https://www.typescriptlang.org/docs/handbook/enums.html
la source
Vous pouvez consulter Enumify , une bibliothèque très bonne et bien équipée pour les énumérations ES6.
la source
Peut-être cette solution? :)
Exemple:
la source
Je préfère l'approche de @ tonethar, avec un peu d'améliorations et de creuser pour mieux comprendre les sous-jacents de l'écosystème ES6 / Node.js. Avec un arrière-plan du côté serveur de la clôture, je préfère l'approche du style fonctionnel autour des primitives de la plate-forme, cela minimise le gonflement du code, la pente glissante dans la vallée de gestion de l'État de l'ombre de la mort en raison de l'introduction de nouveaux types et augmente la lisibilité - rend plus claire l'intention de la solution et de l'algorithme.
Solution avec TDD , ES6 , Node.js , Lodash , Jest , Babel , ESLint
la source
Array.from(Object.assign(args))
ne fait absolument rien. Vous pouvez simplement utiliser...args
directement.Voici mon approche, y compris quelques méthodes d'aide
-
la source
vous pouvez également utiliser le package es6-enum ( https://www.npmjs.com/package/es6-enum ). C'est très simple à utiliser. Voir l'exemple ci-dessous:
la source
Voici mon implémentation d'une énumération Java en JavaScript.
J'ai également inclus des tests unitaires.
la source
Vous pouvez utiliser ES6 Map
la source
const x = Object.freeze({key: 'value'})
plutôt pour obtenir quelque chose qui ressemble et se comporte comme enum dans ES6