Quelle est la syntaxe préférée pour définir des énumérations dans JavaScript?

Quelle est la syntaxe préférée pour définir les énumérations en JavaScript? Quelque chose comme:

my.namespace.ColorEnum = { RED : 0, GREEN : 1, BLUE : 2 } // later on if(currentColor == my.namespace.ColorEnum.RED) { // whatever } 

Ou existe-t-il un langage plus préférable?

Depuis 1.8.5, il est possible de sceller et de geler l’object, définissez donc ce qui précède comme suit:

 var DaysEnum = Object.freeze({"monday":1, "tuesday":2, "wednesday":3, ...}) 

ou

 var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...} Object.freeze(DaysEnum) 

et le tour est joué! JS enums.

Cependant, cela ne vous empêche pas d’atsortingbuer une valeur indésirable à une variable, ce qui est souvent l’objective principal des énumérations:

 let day = DaysEnum.tuesday day = 298832342 // goes through without any errors 

Une manière de garantir un degré plus élevé de sécurité du type (avec énumérations ou autres) consiste à utiliser un outil comme TypeScript ou Flow .

La source

Les citations ne sont pas nécessaires mais je les ai conservées pour la cohérence.

Ce n’est pas vraiment une réponse, mais je dirais que cela fonctionne très bien, personnellement

Cela dit, comme les valeurs n’ont pas d’importance (vous avez utilisé 0, 1, 2), j’utiliserais une chaîne significative au cas où vous souhaiteriez afficher la valeur actuelle.

MISE À JOUR : Merci à tous pour vos commentaires, mais je ne pense pas que ma réponse ci-dessous soit la meilleure façon d’écrire des enums dans Javascript. Voir mon blog pour plus de détails: Enums in Javascript .


Alerter le nom est déjà possible:

 if (currentColor == my.namespace.ColorEnum.RED) { // alert name of currentColor (RED: 0) var col = my.namespace.ColorEnum; for (var name in col) { if (col[name] == col.RED) alert(name); } } 

Alternativement, vous pouvez créer des objects de valeur pour avoir le gâteau et le manger aussi:

 var SIZE = { SMALL : {value: 0, name: "Small", code: "S"}, MEDIUM: {value: 1, name: "Medium", code: "M"}, LARGE : {value: 2, name: "Large", code: "L"} }; var currentSize = SIZE.MEDIUM; if (currentSize == SIZE.MEDIUM) { // this alerts: "1: Medium" alert(currentSize.value + ": " + currentSize.name); } 

En Javascript, comme il s’agit d’un langage dynamic, il est même possible d’append des valeurs enum à l’ensemble plus tard:

 // Add EXTRALARGE size SIZE.EXTRALARGE = {value: 3, name: "Extra Large", code: "XL"}; 

Rappelez-vous que les champs de l’énumération (valeur, nom et code dans cet exemple) ne sont pas nécessaires pour le contrôle d’identité et ne sont là que pour des raisons de commodité. De plus, le nom de la propriété size n’a pas besoin d’être codé en dur, mais peut également être défini dynamicment. Donc, en supposant que vous ne connaissiez que le nom de votre nouvelle valeur enum, vous pouvez toujours l’append sans problème:

 // Add 'Extra Large' size, only knowing it's name var name = "Extra Large"; SIZE[name] = {value: -1, name: name, code: "?"}; 

Bien sûr, cela signifie que certaines hypothèses ne peuvent plus être faites (cette valeur représente l’ordre correct pour la taille par exemple).

Rappelez-vous qu’en Javascript, un object est comme une carte ou une table de hachage. Un ensemble de paires nom-valeur. Vous pouvez les parcourir en boucle ou les manipuler sans en connaître beaucoup d’avance.

PAR EXEMPLE:

 for (var sz in SIZE) { // sz will be the names of the objects in SIZE, so // 'SMALL', 'MEDIUM', 'LARGE', 'EXTRALARGE' var size = SIZE[sz]; // Get the object mapped to the name in sz for (var prop in size) { // Get all the properties of the size object, iterates over // 'value', 'name' and 'code'. You can inspect everything this way. } } 

Et bien sûr, si vous êtes intéressé par les espaces de noms, vous voudrez peut-être jeter un oeil à ma solution pour la gestion simple et puissante des espaces de noms et des dépendances pour javascript: Packages JS

Bottom line: Vous ne pouvez pas.

Vous pouvez faire semblant, mais vous n’obtiendrez pas la sécurité de type. Généralement, cela se fait en créant un dictionnaire simple de valeurs de chaîne mappées à des valeurs entières. Par exemple:

 var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...} Document.Write("Enumerant: " + DaysEnum.tuesday); 

Le problème avec cette approche? Vous pouvez accidentellement redéfinir votre énumérant ou avoir accidentellement des valeurs énumérantes en double. Par exemple:

 DaysEnum.monday = 4; // whoops, monday is now thursday, too 

modifier

Qu’en est-il de Object.freeze d’Artur Czajka? Cela ne vous empêcherait-il pas de passer du lundi au jeudi? – Fry Quad

Absolument, Object.freeze corrigera totalement le problème dont je me suis plaint. J’aimerais rappeler à tous que lorsque j’ai écrit ce qui précède, Object.freeze n’existait pas vraiment.

Maintenant …. maintenant cela ouvre des possibilités très intéressantes.

Modifier 2
Voici une très bonne bibliothèque pour créer des énumérations.

http://www.2ality.com/2011/10/enums.html

Bien que cela ne corresponde probablement pas à toutes les utilisations valables des énumérations, cela va très loin.

Voici ce que nous voulons tous:

 function Enum(constantsList) { for (var i in constantsList) { this[constantsList[i]] = i; } } 

Maintenant vous pouvez créer vos énumérations:

 var YesNo = new Enum(['NO', 'YES']); var Color = new Enum(['RED', 'GREEN', 'BLUE']); 

Ce faisant, les constantes peuvent être acquises de la manière habituelle (YesNo.YES, Color.GREEN) et elles obtiennent une valeur int séquentielle (NO = 0, YES = 1; RED = 0, GREEN = 1, BLUE = 2).

Vous pouvez également append des méthodes en utilisant Enum.prototype:

 Enum.prototype.values = function() { return this.allValues; /* for the above to work, you'd need to do this.allValues = constantsList at the constructor */ }; 

Edit – petite amélioration – maintenant avec varargs: (malheureusement, cela ne fonctionne pas correctement sous IE: S … devrait suivre la version précédente)

 function Enum() { for (var i in arguments) { this[arguments[i]] = i; } } var YesNo = new Enum('NO', 'YES'); var Color = new Enum('RED', 'GREEN', 'BLUE'); 

Dans la plupart des navigateurs modernes, il existe un type de données de primitive de symbole qui peut être utilisé pour créer une énumération. Cela assurera la sécurité de type de l’énumération car chaque valeur de symbole est garantie par JavaScript, c’est-à-dire Symbol() != Symbol() . Par exemple:

 const COLOR = Object.freeze({RED: Symbol(), BLUE: Symbol()}); 

Pour simplifier le débogage, vous pouvez append une description aux valeurs enum:

 const COLOR = Object.freeze({RED: Symbol("RED"), BLUE: Symbol("BLUE")}); 

Démonstration Plunker

Sur GitHub, vous pouvez trouver un wrapper qui simplifie le code requirejs pour initialiser l’énumération:

 const color = new Enum("RED", "BLUE") color.RED.toSsortingng() // Symbol(RED) color.getName(color.RED) // RED color.size // 2 color.values() // Symbol(RED), Symbol(BLUE) color.toSsortingng() // RED,BLUE 

J’ai joué avec ça, comme j’aime mes énumérations. =)

En utilisant Object.defineProperty je pense avoir trouvé une solution quelque peu viable.

Voici un jsfiddle: http://jsfiddle.net/ZV4A6/

En utilisant cette méthode .. vous devriez (en théorie) pouvoir appeler et définir des valeurs d’énumération pour n’importe quel object, sans affecter les autres atsortingbuts de cet object.

 Object.defineProperty(Object.prototype,'Enum', { value: function() { for(i in arguments) { Object.defineProperty(this,arguments[i], { value:parseInt(i), writable:false, enumerable:true, configurable:true }); } return this; }, writable:false, enumerable:false, configurable:false }); 

A cause de l’atsortingbut writable:false cela devrait le rendre sûr.

Vous devriez donc pouvoir créer un object personnalisé, puis appeler Enum() dessus. Les valeurs atsortingbuées commencent à 0 et l’incrément par élément.

 var EnumColors={}; EnumColors.Enum('RED','BLUE','GREEN','YELLOW'); EnumColors.RED; // == 0 EnumColors.BLUE; // == 1 EnumColors.GREEN; // == 2 EnumColors.YELLOW; // == 3 

C’est un ancien que je connais, mais la manière dont il a depuis été implémenté via l’interface TypeScript est la suivante:

 var MyEnum; (function (MyEnum) { MyEnum[MyEnum["Foo"] = 0] = "Foo"; MyEnum[MyEnum["FooBar"] = 2] = "FooBar"; MyEnum[MyEnum["Bar"] = 1] = "Bar"; })(MyEnum|| (MyEnum= {})); 

Cela vous permet de rechercher à la fois MyEnum.Bar qui renvoie 1 et MyEnum[1] qui renvoie “Bar” quel que soit l’ordre de déclaration.

C’est la solution que j’utilise.

 function Enum() { this._enums = []; this._lookups = {}; } Enum.prototype.getEnums = function() { return _enums; } Enum.prototype.forEach = function(callback){ var length = this._enums.length; for (var i = 0; i < length; ++i){ callback(this._enums[i]); } } Enum.prototype.addEnum = function(e) { this._enums.push(e); } Enum.prototype.getByName = function(name) { return this[name]; } Enum.prototype.getByValue = function(field, value) { var lookup = this._lookups[field]; if(lookup) { return lookup[value]; } else { this._lookups[field] = ( lookup = {}); var k = this._enums.length - 1; for(; k >= 0; --k) { var m = this._enums[k]; var j = m[field]; lookup[j] = m; if(j == value) { return m; } } } return null; } function defineEnum(definition) { var k; var e = new Enum(); for(k in definition) { var j = definition[k]; e[k] = j; e.addEnum(j) } return e; } 

Et vous définissez vos énumérations comme ceci:

 var COLORS = defineEnum({ RED : { value : 1, ssortingng : 'red' }, GREEN : { value : 2, ssortingng : 'green' }, BLUE : { value : 3, ssortingng : 'blue' } }); 

Et voici comment vous accédez à vos énumérations:

 COLORS.BLUE.ssortingng COLORS.BLUE.value COLORS.getByName('BLUE').ssortingng COLORS.getByValue('value', 1).ssortingng COLORS.forEach(function(e){ // do what you want with e }); 

J’utilise généralement les deux dernières méthodes pour mapper les énumérations à partir d’objects de message.

Quelques avantages à cette approche:

  • Facile à déclarer des énumérations
  • Facile d’accéder à vos énumérations
  • Vos énumérations peuvent être des types complexes
  • La classe Enum a une mise en cache associative si vous utilisez beaucoup getByValue

Quelques inconvénients:

  • Une gestion de la mémoire désordonnée se poursuit, alors que je garde les références aux énumérations
  • Toujours pas de type sécurité

Si vous utilisez Backbone , vous pouvez obtenir gratuitement des fonctionnalités complètes (rechercher par identifiant, nom, membres personnalisés) à l’aide de Backbone.Collection .

 // enum instance members, optional var Color = Backbone.Model.extend({ print : function() { console.log("I am " + this.get("name")) } }); // enum creation var Colors = new Backbone.Collection([ { id : 1, name : "Red", rgb : 0xFF0000}, { id : 2, name : "Green" , rgb : 0x00FF00}, { id : 3, name : "Blue" , rgb : 0x0000FF} ], { model : Color }); // Expose members through public fields. Colors.each(function(color) { Colors[color.get("name")] = color; }); // using Colors.Red.print() 

Dans ES7 , vous pouvez faire un élégant ENUM reposant sur des atsortingbuts statiques:

 class ColorEnum { static RED = 0 ; static GREEN = 1; static BLUE = 2; } 

puis

 if (currentColor === ColorEnum.GREEN ) {/*-- coding --*/} 

L’avantage (d’utiliser une classe au lieu d’un object littéral) est d’avoir une classe parent Enum alors tous vos Enums étendront cette classe.

  class ColorEnum extends Enum {/*....*/} 

Créez un littéral d’object:

 const Modes = { DRAGGING: 'drag', SCALING: 'scale', CLICKED: 'click' }; 

vos réponses sont beaucoup trop compliquées

 var buildSet = function(array) { var set = {}; for (var i in array) { var item = array[i]; set[item] = item; } return set; } var myEnum = buildSet(['RED','GREEN','BLUE']); // myEnum.RED == 'RED' ...etc 

J’ai modifié la solution d’André ‘Fi’:

  function Enum() { var that = this; for (var i in arguments) { that[arguments[i]] = i; } this.name = function(value) { for (var key in that) { if (that[key] == value) { return key; } } }; this.exist = function(value) { return (typeof that.name(value) !== "undefined"); }; if (Object.freeze) { Object.freeze(that); } } 

Tester:

 var Color = new Enum('RED', 'GREEN', 'BLUE'); undefined Color.name(Color.REDs) undefined Color.name(Color.RED) "RED" Color.exist(Color.REDs) false Color.exist(Color.RED) true 

Utiliser des proxy Javascript

Une caractéristique très intéressante de Enums que vous obtenez des langages traditionnels est qu’ils s’élèvent (jettent une erreur de compilation) si vous essayez d’accéder à un énumérateur qui n’existe pas.

En plus de geler la structure enum simulée pour éviter que des valeurs supplémentaires ne soient ajoutées accidentellement / malicieusement, aucune des autres réponses ne traite de cette caractéristique insortingnsèque de Enums.

Comme vous le savez probablement, l’access à des membres non existants en JavaScript renvoie simplement undefined et ne fait pas exploser votre code. Les énumérateurs étant des constantes prédéfinies (c.-à-d. Les jours de la semaine), il ne devrait jamais y avoir de cas où un énumérateur ne serait pas défini.

Ne vous méprenez pas, le comportement de JavaScript consistant à renvoyer une undefined lors de l’access à des propriétés non définies est en réalité une fonctionnalité très puissante du langage, mais ce n’est pas une fonctionnalité que vous souhaitez utiliser lorsque vous tentez de simuler des structures Enum traditionnelles.

C’est où les objects proxy brillent. Les proxies ont été standardisés dans la langue avec l’introduction de ES6 (ES2015). Voici la description de MDN:

L’object Proxy est utilisé pour définir un comportement personnalisé pour les opérations fondamentales (par exemple, recherche de propriété, affectation, énumération, invocation de fonctions, etc.).

Semblables à un proxy de serveur Web, les proxys JavaScript peuvent intercepter des opérations sur des objects (en utilisant des “pièges”, appelez-les si vous le souhaitez) et vous permettre d’effectuer diverses vérifications, actions et / ou manipulations dans certains cas, arrêter complètement les opérations, ce qui est exactement ce que nous voulons faire si et quand nous essayons de référencer un énumérateur qui n’existe pas).

Voici un exemple conçu qui utilise l’object Proxy pour imiter Enums. Les énumérateurs de cet exemple sont des méthodes HTTP standard (“GET”, “POST”, etc.):

 // Generic Factory Function for creating enums (10 lines) // Feel free to add this to your utility library in // your codebase and profit! Note: As Proxies are an ES6 // feature, some browsers/clients may not support it and // you may need to transstack using a service like babel function createEnum(enumObj) { // Instantiating a `Proxy` object requires two parameters, // a `target` object and a `handler`. We first define the handler, // then use the handler to instantiate a Proxy. // a proxy handler is simply an object whose properties // are functions which define the behavior of the proxy // when an operation is performed on it. For enums, we // need to define behavior that lets us check what enumerator // is being accessed. This can be done by defining the "get" trap const enumHandler = { get: function(target, name) { if (target[name]) { return target[name] } throw new Error(`No such enumerator: ${name}`) } } // Freeze the target object to prevent modifications return new Proxy(Object.freeze(enumObj), enumHandler) } // Now that we have a generic way of creating Enums, lets create our first Enum! const httpMethods = createEnum({ DELETE: "DELETE", GET: "GET", OPTIONS: "OPTIONS", PATCH: "PATCH", POST: "POST", PUT: "PUT" }) // Sanity checks console.log(httpMethods.DELETE) // logs "DELETE" httpMethods.delete = "delete" // no effect due to Object.freeze, fails silently (no error thrown) try { console.log(httpMethods.delete) } catch (e) { console.log("Error: ", e.message) } // throws an error "Uncaught Error: No such enumerator: delete" 

La syntaxe “Perfered” par la plupart des gens a déjà été listée ci-dessus. Cependant, il existe un problème majeur: la performance. Pas une seule des réponses ci-dessus n’est très performante et elles gonflent toutes la taille du code à l’extrême. Pour des performances réelles, une facilité de lecture du code et une réduction sans précédent de la taille du code par minification, il s’agit de la méthode correcte pour effectuer les énumérations.

 const ENUM_COLORENUM_RED = 0, ENUM_COLORENUM_GREEN = 1, ENUM_COLORENUM_BLUE = 2, ENUMLEN_COLORENUM = 3; // later on if(currentColor == ENUM_COLORENUM_RED) { // whatever } 

En outre, cette syntaxe permet une classe claire et concise qui s’étend comme indiqué ci-dessous.

(Longueur: 2450 octets)

 (function(window){ "use ssortingct"; var parseInt = window.parseInt const ENUM_PIXELCOLOR_TYPE = 0, // is a ENUM_PIXELTYPE ENUMLEN_PIXELCOLOR = 1, ENUM_SOLIDCOLOR_R = ENUMLEN_PIXELCOLOR+0, ENUM_SOLIDCOLOR_G = ENUMLEN_PIXELCOLOR+1, ENUM_SOLIDCOLOR_B = ENUMLEN_PIXELCOLOR+2, ENUMLEN_SOLIDCOLOR = ENUMLEN_PIXELCOLOR+3, ENUM_ALPHACOLOR_R = ENUMLEN_PIXELCOLOR+0, ENUM_ALPHACOLOR_G = ENUMLEN_PIXELCOLOR+1, ENUM_ALPHACOLOR_B = ENUMLEN_PIXELCOLOR+2, ENUM_ALPHACOLOR_A = ENUMLEN_PIXELCOLOR+3, ENUMLEN_ALPHACOLOR = ENUMLEN_PIXELCOLOR+4, ENUM_PIXELTYPE_SOLID = 0, ENUM_PIXELTYPE_ALPHA = 1, ENUM_PIXELTYPE_UNKNOWN = 2, ENUMLEN_PIXELTYPE = 2; function parseHexColor(rawstr) { rawstr = rawstr.sortingm().subssortingng(1); var result = []; if (rawstr.length === 8) { result[ENUM_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_ALPHA; result[ENUM_ALPHACOLOR_R] = parseInt(rawstr.subssortingng(0,2), 16); result[ENUM_ALPHACOLOR_G] = parseInt(rawstr.subssortingng(2,4), 16); result[ENUM_ALPHACOLOR_B] = parseInt(rawstr.subssortingng(4,6), 16); result[ENUM_ALPHACOLOR_A] = parseInt(rawstr.subssortingng(4,6), 16); } else if (rawstr.length === 4) { result[ENUM_ALPHACOLOR_R] = parseInt(rawstr[0], 16) * 0x11; result[ENUM_ALPHACOLOR_G] = parseInt(rawstr[1], 16) * 0x11; result[ENUM_ALPHACOLOR_B] = parseInt(rawstr[2], 16) * 0x11; result[ENUM_ALPHACOLOR_A] = parseInt(rawstr[3], 16) * 0x11; } else if (rawstr.length === 6) { result[ENUM_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_SOLID; result[ENUM_SOLIDCOLOR_R] = parseInt(rawstr.subssortingng(0,2), 16); result[ENUM_SOLIDCOLOR_G] = parseInt(rawstr.subssortingng(2,4), 16); result[ENUM_SOLIDCOLOR_B] = parseInt(rawstr.subssortingng(4,6), 16); } else if (rawstr.length === 3) { result[ENUM_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_SOLID; result[ENUM_SOLIDCOLOR_R] = parseInt(rawstr[0], 16) * 0x11; result[ENUM_SOLIDCOLOR_G] = parseInt(rawstr[1], 16) * 0x11; result[ENUM_SOLIDCOLOR_B] = parseInt(rawstr[2], 16) * 0x11; } else { result[ENUM_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_UNKNOWN; } return result; } // the red component of green console.log(parseHexColor("#0f0")[ENUM_SOLIDCOLOR_R]); // the alpha of transparent purple console.log(parseHexColor("#f0f7")[ENUM_ALPHACOLOR_A]); // the enumerated array for turquoise console.log(parseHexColor("#40E0D0")); })(self); 

IE8 ne prend pas en charge la méthode freeze ().
Source: http://kangax.github.io/compat-table/es5/ , Cliquez sur “Afficher les navigateurs obsolètes?” en haut, et vérifier IE8 et geler l’intersection de la colonne.

Dans mon projet de jeu actuel, j’ai utilisé ci-dessous, car peu de clients utilisent encore IE8:

 var CONST_WILD_TYPES = { REGULAR: 'REGULAR', EXPANDING: 'EXPANDING', STICKY: 'STICKY', SHIFTING: 'SHIFTING' }; 

Nous pourrions aussi faire:

 var CONST_WILD_TYPES = { REGULAR: 'RE', EXPANDING: 'EX', STICKY: 'ST', SHIFTING: 'SH' }; 

ou même ceci:

 var CONST_WILD_TYPES = { REGULAR: '1', EXPANDING: '2', STICKY: '3', SHIFTING: '4' }; 

Le dernier, semble le plus efficace pour la chaîne, il réduit votre bande passante totale si vous avez le serveur et le client échangeant ces données.
Bien sûr, il est maintenant de votre devoir de vous assurer qu’il n’y a pas de conflit dans les données (les RE, EX, etc. doivent être uniques, et les 1, 2, etc. doivent être uniques). Notez que vous devez les conserver pour toujours pour la compatibilité descendante.

Affectation:

 var wildType = CONST_WILD_TYPES.REGULAR; 

Comparaison:

 if (wildType === CONST_WILD_TYPES.REGULAR) { // do something here } 

J’ai créé une classe Enum qui peut récupérer des valeurs ET des noms en O (1). Il peut également générer un tableau d’objects contenant tous les noms et valeurs.

 function Enum(obj) { // Names must be unique, Values do not. // Putting same values for different Names is risky for this implementation this._reserved = { _namesObj: {}, _objArr: [], _namesArr: [], _valuesArr: [], _selectOptionsHTML: "" }; for (k in obj) { if (obj.hasOwnProperty(k)) { this[k] = obj[k]; this._reserved._namesObj[obj[k]] = k; } } } (function () { this.GetName = function (val) { if (typeof this._reserved._namesObj[val] === "undefined") return null; return this._reserved._namesObj[val]; }; this.GetValue = function (name) { if (typeof this[name] === "undefined") return null; return this[name]; }; this.GetObjArr = function () { if (this._reserved._objArr.length == 0) { var arr = []; for (k in this) { if (this.hasOwnProperty(k)) if (k != "_reserved") arr.push({ Name: k, Value: this[k] }); } this._reserved._objArr = arr; } return this._reserved._objArr; }; this.GetNamesArr = function () { if (this._reserved._namesArr.length == 0) { var arr = []; for (k in this) { if (this.hasOwnProperty(k)) if (k != "_reserved") arr.push(k); } this._reserved._namesArr = arr; } return this._reserved._namesArr; }; this.GetValuesArr = function () { if (this._reserved._valuesArr.length == 0) { var arr = []; for (k in this) { if (this.hasOwnProperty(k)) if (k != "_reserved") arr.push(this[k]); } this._reserved._valuesArr = arr; } return this._reserved._valuesArr; }; this.GetSelectOptionsHTML = function () { if (this._reserved._selectOptionsHTML.length == 0) { var html = ""; for (k in this) { if (this.hasOwnProperty(k)) if (k != "_reserved") html += ""; } this._reserved._selectOptionsHTML = html; } return this._reserved._selectOptionsHTML; }; }).call(Enum.prototype); 

Vous pouvez l’initier comme ceci:

 var enum1 = new Enum({ item1: 0, item2: 1, item3: 2 }); 

To fetch a value (like Enums in C#):

 var val2 = enum1.item2; 

To fetch a name for a value (can be ambiguous when putting the same value for different names):

 var name1 = enum1.GetName(0); // "item1" 

To get an array with each name & value in an object:

 var arr = enum1.GetObjArr(); 

Will generate:

 [{ Name: "item1", Value: 0}, { ... }, ... ] 

You can also get the html select options readily:

 var html = enum1.GetSelectOptionsHTML(); 

Which holds:

 "..." 

A quick and simple way would be :

 var Colors = function(){ return { 'WHITE':0, 'BLACK':1, 'RED':2, 'GREEN':3 } }(); console.log(Colors.WHITE) //this prints out "0" 

Here’s a couple different ways to implement TypeScript enums .

The easiest way is to just iterate over an object, adding inverted key-value pairs to the object. The only drawback is that you must manually set the value for each member.

 function _enum(list) { for (var key in list) { list[list[key] = list[key]] = key; } return Object.freeze(list); } var Color = _enum({ Red: 0, Green: 5, Blue: 2 }); // Color → {0: "Red", 2: "Blue", 5: "Green", "Red": 0, "Green": 5, "Blue": 2} // Color.Red → 0 // Color.Green → 5 // Color.Blue → 2 // Color[5] → Green // Color.Blue > Color.Green → false 

And here’s a lodash mixin to create an enum using a ssortingng. While this version is a little bit more involved, it does the numbering automatically for you. All the lodash methods used in this example have a regular JavaScript equivalent, so you can easily switch them out if you want.

 function enum() { var key, val = -1, list = {}; _.reduce(_.toArray(arguments), function(result, kvp) { kvp = kvp.split("="); key = _.sortingm(kvp[0]); val = _.parseInt(kvp[1]) || ++val; result[result[val] = key] = val; return result; }, list); return Object.freeze(list); } // Add enum to lodash _.mixin({ "enum": enum }); var Color = _.enum( "Red", "Green", "Blue = 5", "Yellow", "Purple = 20", "Gray" ); // Color.Red → 0 // Color.Green → 1 // Color.Blue → 5 // Color.Yellow → 6 // Color.Purple → 20 // Color.Gray → 21 // Color[5] → Blue 

I’ve just published an NPM package gen_enum allows you to create Enum data structure in Javascript quickly:

 var genEnum = require('gen_enum'); var AppMode = genEnum('SIGN_UP, LOG_IN, FORGOT_PASSWORD'); var curMode = AppMode.LOG_IN; console.log(curMode.isLogIn()); // output true console.log(curMode.isSignUp()); // output false console.log(curMode.isForgotPassword()); // output false 

One nice thing about this little tool is in modern environment (including nodejs and IE 9+ browsers) the returned Enum object is immutable.

For more information please checkout https://github.com/greenlaw110/enumjs

Mises à jour

I obsolete gen_enum package and merge the function into constjs package, which provides more features including immutable objects, JSON ssortingng deserialization, ssortingng constants and bitmap generation etc. Checkout https://www.npmjs.com/package/constjs for more information

To upgrade from gen_enum to constjs just change the statement

 var genEnum = require('gen_enum'); 

à

 var genEnum = require('constjs').enum; 

I came up with this approach which is modeled after enums in Java. These are type-safe, and so you can perform instanceof checks as well.

You can define enums like this:

 var Days = Enum.define("Days", ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]); 

Days now refers to the Days enum:

 Days.Monday instanceof Days; // true Days.Friday.name(); // "Friday" Days.Friday.ordinal(); // 4 Days.Sunday === Days.Sunday; // true Days.Sunday === Days.Friday; // false Days.Sunday.toSsortingng(); // "Sunday" Days.toSsortingng() // "Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } " Days.values().map(function(e) { return e.name(); }); //["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] Days.values()[4].name(); //"Friday" Days.fromName("Thursday") === Days.Thursday // true Days.fromName("Wednesday").name() // "Wednesday" Days.Friday.fromName("Saturday").name() // "Saturday" 

The implementation:

 var Enum = (function () { /** * Function to define an enum * @param typeName - The name of the enum. * @param constants - The constants on the enum. Can be an array of ssortingngs, or an object where each key is an enum * constant, and the values are objects that describe atsortingbutes that can be attached to the associated constant. */ function define(typeName, constants) { /** Check Arguments **/ if (typeof typeName === "undefined") { throw new TypeError("A name is required."); } if (!(constants instanceof Array) && (Object.getPrototypeOf(constants) !== Object.prototype)) { throw new TypeError("The constants parameter must either be an array or an object."); } else if ((constants instanceof Array) && constants.length === 0) { throw new TypeError("Need to provide at least one constant."); } else if ((constants instanceof Array) && !constants.reduce(function (isSsortingng, element) { return isSsortingng && (typeof element === "ssortingng"); }, true)) { throw new TypeError("One or more elements in the constant array is not a ssortingng."); } else if (Object.getPrototypeOf(constants) === Object.prototype && !Object.keys(constants).reduce(function (isObject, constant) { return Object.getPrototypeOf(constants[constant]) === Object.prototype; }, true)) { throw new TypeError("One or more constants do not have an associated object-value."); } var isArray = (constants instanceof Array); var isObject = !isArray; /** Private sentinel-object used to guard enum constructor so that no one else can create enum instances **/ function __() { }; /** Dynamically define a function with the same name as the enum we want to define. **/ var __enum = new Function(["__"], "return function " + typeName + "(sentinel, name, ordinal) {" + "if(!(sentinel instanceof __)) {" + "throw new TypeError(\"Cannot instantiate an instance of " + typeName + ".\");" + "}" + "this.__name = name;" + "this.__ordinal = ordinal;" + "}" )(__); /** Private objects used to maintain enum instances for values(), and to look up enum instances for fromName() **/ var __values = []; var __dict = {}; /** Attach values() and fromName() methods to the class itself (kind of like static methods). **/ Object.defineProperty(__enum, "values", { value: function () { return __values; } }); Object.defineProperty(__enum, "fromName", { value: function (name) { var __constant = __dict[name] if (__constant) { return __constant; } else { throw new TypeError(typeName + " does not have a constant with name " + name + "."); } } }); /** * The following methods are available to all instances of the enum. values() and fromName() need to be * available to each constant, and so we will attach them on the prototype. But really, they're just * aliases to their counterparts on the prototype. */ Object.defineProperty(__enum.prototype, "values", { value: __enum.values }); Object.defineProperty(__enum.prototype, "fromName", { value: __enum.fromName }); Object.defineProperty(__enum.prototype, "name", { value: function () { return this.__name; } }); Object.defineProperty(__enum.prototype, "ordinal", { value: function () { return this.__ordinal; } }); Object.defineProperty(__enum.prototype, "valueOf", { value: function () { return this.__name; } }); Object.defineProperty(__enum.prototype, "toSsortingng", { value: function () { return this.__name; } }); /** * If constants was an array, we can the element values directly. Otherwise, we will have to use the keys * from the constants object. */ var _constants = constants; if (isObject) { _constants = Object.keys(constants); } /** Iterate over all constants, create an instance of our enum for each one, and attach it to the enum type **/ _constants.forEach(function (name, ordinal) { // Create an instance of the enum var __constant = new __enum(new __(), name, ordinal); // If constants was an object, we want to attach the provided atsortingbutes to the instance. if (isObject) { Object.keys(constants[name]).forEach(function (attr) { Object.defineProperty(__constant, attr, { value: constants[name][attr] }); }); } // Freeze the instance so that it cannot be modified. Object.freeze(__constant); // Attach the instance using the provided name to the enum type itself. Object.defineProperty(__enum, name, { value: __constant }); // Update our private objects __values.push(__constant); __dict[name] = __constant; }); /** Define a friendly toSsortingng method for the enum **/ var ssortingng = typeName + " { " + __enum.values().map(function (c) { return c.name(); }).join(", ") + " } "; Object.defineProperty(__enum, "toSsortingng", { value: function () { return ssortingng; } }); /** Freeze our private objects **/ Object.freeze(__values); Object.freeze(__dict); /** Freeze the prototype on the enum and the enum itself **/ Object.freeze(__enum.prototype); Object.freeze(__enum); /** Return the enum **/ return __enum; } return { define: define } })(); 

Even though only static methods (and not static properties) are supported in ES2015 (see here as well, §15.2.2.2), curiously you can use the below with Babel with the es2015 preset:

 class CellState { v: ssortingng; constructor(v: ssortingng) { this.v = v; Object.freeze(this); } static EMPTY = new CellState('e'); static OCCUPIED = new CellState('o'); static HIGHLIGHTED = new CellState('h'); static values = function(): Array { const rv = []; rv.push(CellState.EMPTY); rv.push(CellState.OCCUPIED); rv.push(CellState.HIGHLIGHTED); return rv; } } Object.freeze(CellState); 

I found this to be working as expected even across modules (eg importing the CellState enum from another module) and also when I import a module using Webpack.

The advantage this method has over most other answers is that you can use it alongside a static type checker (eg Flow ) and you can assert, at development time using static type checking, that your variables, parameters, etc. are of the specific CellState “enum” rather than some other enum (which would be impossible to distinguish if you used generic objects or symbols).

mettre à jour

The above code has a deficiency in that it allows one to create additional objects of type CellState (even though one can’t assign them to the static fields of CellState since it’s frozen). Still, the below more refined code offers the following advantages:

  1. no more objects of type CellState may be created
  2. you are guaranteed that no two enum instances are assigned the same code
  3. utility method to get the enum back from a ssortingng representation
  4. the values function that returns all instances of the enum does not have to create the return value in the above, manual (and error-prone) way.

     'use ssortingct'; class Status { constructor(code, displayName = code) { if (Status.INSTANCES.has(code)) throw new Error(`duplicate code value: [${code}]`); if (!Status.canCreateMoreInstances) throw new Error(`attempt to call constructor(${code}`+ `, ${displayName}) after all static instances have been created`); this.code = code; this.displayName = displayName; Object.freeze(this); Status.INSTANCES.set(this.code, this); } toSsortingng() { return `[code: ${this.code}, displayName: ${this.displayName}]`; } static INSTANCES = new Map(); static canCreateMoreInstances = true; // the values: static ARCHIVED = new Status('Archived'); static OBSERVED = new Status('Observed'); static SCHEDULED = new Status('Scheduled'); static UNOBSERVED = new Status('Unobserved'); static UNTRIGGERED = new Status('Unsortingggered'); static values = function() { return Array.from(Status.INSTANCES.values()); } static fromCode(code) { if (!Status.INSTANCES.has(code)) throw new Error(`unknown code: ${code}`); else return Status.INSTANCES.get(code); } } Status.canCreateMoreInstances = false; Object.freeze(Status); exports.Status = Status; 

As of writing, October 2014 – so here is a contemporary solution. Am writing the solution as a Node Module, and have included a test using Mocha and Chai, as well as underscoreJS. You can easily ignore these, and just take the Enum code if preferred.

Seen a lot of posts with overly convoluted libraries etc. The solution to getting enum support in Javascript is so simple it really isn’t needed. Voici le code:

File: enums.js

 _ = require('underscore'); var _Enum = function () { var keys = _.map(arguments, function (value) { return value; }); var self = { keys: keys }; for (var i = 0; i < arguments.length; i++) { self[keys[i]] = i; } return self; }; var fileFormatEnum = Object.freeze(_Enum('CSV', 'TSV')); var encodingEnum = Object.freeze(_Enum('UTF8', 'SHIFT_JIS')); exports.fileFormatEnum = fileFormatEnum; exports.encodingEnum = encodingEnum; 

And a test to illustrate what it gives you:

file: enumsSpec.js

 var chai = require("chai"), assert = chai.assert, expect = chai.expect, should = chai.should(), enums = require('./enums'), _ = require('underscore'); describe('enums', function () { describe('fileFormatEnum', function () { it('should return expected fileFormat enum declarations', function () { var fileFormatEnum = enums.fileFormatEnum; should.exist(fileFormatEnum); assert('{"keys":["CSV","TSV"],"CSV":0,"TSV":1}' === JSON.ssortingngify(fileFormatEnum), 'Unexpected format'); assert('["CSV","TSV"]' === JSON.ssortingngify(fileFormatEnum.keys), 'Unexpected keys format'); }); }); describe('encodingEnum', function () { it('should return expected encoding enum declarations', function () { var encodingEnum = enums.encodingEnum; should.exist(encodingEnum); assert('{"keys":["UTF8","SHIFT_JIS"],"UTF8":0,"SHIFT_JIS":1}' === JSON.ssortingngify(encodingEnum), 'Unexpected format'); assert('["UTF8","SHIFT_JIS"]' === JSON.ssortingngify(encodingEnum.keys), 'Unexpected keys format'); }); }); }); 

As you can see, you get an Enum factory, you can get all the keys simply by calling enum.keys, and you can match the keys themselves to integer constants. And you can reuse the factory with different values, and export those generated Enums using Node's modular approach.

Once again, if you are just a casual user, or in the browser etc, just take the factory part of the code, potentially removing underscore library too if you don't wish to use it in your code.

 var ColorEnum = { red: {}, green: {}, blue: {} } 

You don’t need to make sure you don’t assign duplicate numbers to different enum values this way. A new object gets instantiated and assigned to all enum values.

Vous pouvez faire quelque chose comme ça

 function Enum(){ this.add.apply(this,arguments); } Enum.prototype.add = function(){ for (var i in arguments) { this[arguments[i]] = new Ssortingng(arguments[i]); } }; Enum.prototype.toList = function(){ return Object.keys(this) }; var STATUS = new Enum("CLOSED","PENDING"); var STATE = new Enum("CLOSED","PENDING"); STATE.CLOSED === STATUS.CLOSED // false; STATE.CLOSED === "CLOSED" // false; STATE.CLOSED.toSsortingng() === "CLOSED" // true; 

As defined in this library. https://github.com/webmodule/foo/blob/master/foo.js#L217

Simplest solution:

Créer

 var Status = Object.freeze({ "Connecting":0, "Ready":1, "Loading":2, "Processing": 3 }); 

Get Value

 console.log(Status.Ready) // 1 

Get Key

 console.log(Object.keys(Status)[Status.Ready]) // Ready 

This is how Typescript translates it’s enum into Javascript:

 var makeEnum = function(obj) { obj[ obj['Active'] = 1 ] = 'Active'; obj[ obj['Closed'] = 2 ] = 'Closed'; obj[ obj['Deleted'] = 3 ] = 'Deleted'; } 

Now:

 makeEnum( NewObj = {} ) // => {1: "Active", 2: "Closed", 3: "Deleted", Active: 1, Closed: 2, Deleted: 3} 

At first I was confused why obj[1] returns 'Active' , but then realised that its dead simple – Assignment operator assigns value and then returns it:

 obj['foo'] = 1 // => 1 

I had done it a while ago using a mixture of __defineGetter__ and __defineSetter__ or defineProperty depending on the JS version.

Here’s the enum generating function I made: https://gist.github.com/gfarrell/6716853

You’d use it like this:

 var Colours = Enum('RED', 'GREEN', 'BLUE'); 

And it would create an immutable ssortingng:int dictionary (an enum).

It’s easy to use, I think. https://stackoverflow.com/a/32245370/4365315

 var A = {a:11, b:22}, enumA = new TypeHelper(A); if(enumA.Value === Ab || enumA.Key === "a"){ ... } var keys = enumA.getAsList();//[object, object] //set enumA.setType(22, false);//setType(val, isKey) enumA.setType("a", true); enumA.setTypeByIndex(1); 

UPDATE:

There is my helper codes( TypeHelper ).

 var Helper = { isEmpty: function (obj) { return !obj || obj === null || obj === undefined || Array.isArray(obj) && obj.length === 0; }, isObject: function (obj) { return (typeof obj === 'object'); }, sortObjectKeys: function (object) { return Object.keys(object) .sort(function (a, b) { c = a - b; return c }); }, containsItem: function (arr, item) { if (arr && Array.isArray(arr)) { return arr.indexOf(item) > -1; } else { return arr === item; } }, pushArray: function (arr1, arr2) { if (arr1 && arr2 && Array.isArray(arr1)) { arr1.push.apply(arr1, Array.isArray(arr2) ? arr2 : [arr2]); } } }; function TypeHelper() { var _types = arguments[0], _defTypeIndex = 0, _currentType, _value, _allKeys = Helper.sortObjectKeys(_types); if (arguments.length == 2) { _defTypeIndex = arguments[1]; } Object.defineProperties(this, { Key: { get: function () { return _currentType; }, set: function (val) { _currentType.setType(val, true); }, enumerable: true }, Value: { get: function () { return _types[_currentType]; }, set: function (val) { _value.setType(val, false); }, enumerable: true } }); this.getAsList = function (keys) { var list = []; _allKeys.forEach(function (key, idx, array) { if (key && _types[key]) { if (!Helper.isEmpty(keys) && Helper.containsItem(keys, key) || Helper.isEmpty(keys)) { var json = {}; json.Key = key; json.Value = _types[key]; Helper.pushArray(list, json); } } }); return list; }; this.setType = function (value, isKey) { if (!Helper.isEmpty(value)) { Object.keys(_types).forEach(function (key, idx, array) { if (Helper.isObject(value)) { if (value && value.Key == key) { _currentType = key; } } else if (isKey) { if (value && value.toSsortingng() == key.toSsortingng()) { _currentType = key; } } else if (value && value.toSsortingng() == _types[key]) { _currentType = key; } }); } else { this.setDefaultType(); } return isKey ? _types[_currentType] : _currentType; }; this.setTypeByIndex = function (index) { for (var i = 0; i < _allKeys.length; i++) { if (index === i) { _currentType = _allKeys[index]; break; } } }; this.setDefaultType = function () { this.setTypeByIndex(_defTypeIndex); }; this.setDefaultType(); } var TypeA = { "-1": "Any", "2": "2L", "100": "100L", "200": "200L", "1000": "1000L" }; var enumA = new TypeHelper(TypeA, 4); document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "
"); enumA.setType("200L", false); document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "
"); enumA.setDefaultType(); document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "
"); enumA.setTypeByIndex(1); document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "
"); document.writeln("is equals = ", (enumA.Value == TypeA["2"]));