javascript - समझ - प्रपत्र एचटीएमएल




जावास्क्रिप्ट में enums परिभाषित करने के लिए पसंदीदा वाक्यविन्यास क्या है? (20)

IE8 फ्रीज () विधि का समर्थन नहीं करता है।
स्रोत: http://kangax.github.io/compat-table/es5/ , "अप्रचलित ब्राउज़र्स दिखाएं" पर क्लिक करें? शीर्ष पर, और IE8 जांचें और पंक्ति कॉल चौराहे को फ्रीज करें।

मेरे वर्तमान गेम प्रोजेक्ट में, मैंने नीचे उपयोग किया है, क्योंकि कुछ ग्राहक अभी भी IE8 का उपयोग करते हैं:

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

हम यह भी कर सकते थे:

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

या यहां तक ​​कि यह भी:

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

आखिरी वाला, स्ट्रिंग के लिए सबसे अधिक कुशल लगता है, यदि आपके पास सर्वर और क्लाइंट इस डेटा का आदान-प्रदान कर रहा है तो यह आपकी कुल बैंडविड्थ को कम कर देता है।
बेशक, अब यह सुनिश्चित करना आपका कर्तव्य है कि डेटा में कोई संघर्ष नहीं है (आरई, एक्स, इत्यादि अद्वितीय होना चाहिए, 1, 2, आदि अद्वितीय होना चाहिए)। ध्यान दें कि आपको हमेशा पिछड़े संगतता के लिए इन्हें बनाए रखने की आवश्यकता है।

नियत कार्य:

var wildType = CONST_WILD_TYPES.REGULAR;

तुलना:

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

जावास्क्रिप्ट में enums परिभाषित करने के लिए पसंदीदा वाक्यविन्यास क्या है? कुछ इस तरह:

my.namespace.ColorEnum = {
    RED : 0,
    GREEN : 1,
    BLUE : 2
}

// later on

if(currentColor == my.namespace.ColorEnum.RED) {
   // whatever
}

या क्या एक और बेहतर मुहावरे है?


अधिकांश आधुनिक ब्राउज़रों में, एक symbol आदिम डेटा प्रकार होता है जिसे गणना बनाने के लिए उपयोग किया जा सकता है। यह enum की प्रकार की सुरक्षा सुनिश्चित करेगा क्योंकि जावास्क्रिप्ट द्वारा प्रत्येक प्रतीक मान की गारंटी अद्वितीय है, यानी Symbol() != Symbol() । उदाहरण के लिए:

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

डीबगिंग को सरल बनाने के लिए, आप enum मानों में एक विवरण जोड़ सकते हैं:

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

प्लंकर डेमो

GitHub आप एक रैपर पा सकते हैं जो enum को प्रारंभ करने के लिए आवश्यक कोड को सरल बनाता है:

const color = new Enum("RED", "BLUE")

color.RED.toString() // Symbol(RED)
color.getName(color.RED) // RED
color.size // 2
color.values() // Symbol(RED), Symbol(BLUE)
color.toString() // RED,BLUE

आप ऐसा कुछ कर सकते हैं

function Enum(){
  this.add.apply(this,arguments);
}

Enum.prototype.add = function(){
  for (var i in arguments) {
    this[arguments[i]] = new String(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.toString() === "CLOSED"  // true;

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


आपके उत्तर बहुत जटिल हैं

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

एक त्वरित और सरल तरीका होगा:

var Colors = function(){
return {
    'WHITE':0,
    'BLACK':1,
    'RED':2,
    'GREEN':3
    }
}();

console.log(Colors.WHITE)  //this prints out "0"

एक वस्तु शाब्दिक बनाएँ:

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

मैं this दृष्टिकोण के साथ आया जो जावा में enums के बाद मॉडलिंग किया गया है। ये टाइप-सुरक्षित हैं, और इसलिए आप जांच के instanceof कर सकते हैं।

आप इस तरह के enums परिभाषित कर सकते हैं:

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

Days अब 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.toString(); // "Sunday"

Days.toString() // "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"

कार्यान्वयन:

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 strings, or an object where each key is an enum
     * constant, and the values are objects that describe attributes 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 (isString, element) {
                return isString && (typeof element === "string");
            }, true)) {

            throw new TypeError("One or more elements in the constant array is not a string.");

        } 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, "toString", {
            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 attributes 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 toString method for the enum **/
        var string = typeName + " { " + __enum.values().map(function (c) {
                return c.name();
            }).join(", ") + " } ";

        Object.defineProperty(__enum, "toString", {
            value: function () {
                return string;
            }
        });

        /** 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
    }

})();

मैं इसके साथ खेल रहा हूं, क्योंकि मैं अपने enums प्यार करता हूँ। =)

Object.defineProperty का उपयोग करना मुझे लगता है कि मैं कुछ हद तक व्यवहार्य समाधान के साथ आया था।

यहां एक jsfiddle है: http://jsfiddle.net/ZV4A6/

इस विधि का उपयोग करना .. आपको उस सिद्धांत के अन्य विशेषताओं को प्रभावित किए बिना, किसी भी वस्तु के लिए enum मानों को कॉल और परिभाषित करने में सक्षम होना चाहिए।

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

writable:false विशेषता के कारण writable:false इसे इसे सुरक्षित टाइप करना चाहिए

तो आप एक कस्टम ऑब्जेक्ट बनाने में सक्षम होना चाहिए, फिर उस पर Enum() को कॉल करें। सौंपा गया मान 0 से शुरू होता है और प्रति आइटम बढ़ता है।

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

मैंने अभी एक एनपीएम पैकेज प्रकाशित किया है gen_enum आपको जावास्क्रिप्ट में gen_enum डेटा संरचना को जल्दी से बनाने की अनुमति देता है:

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 

इस छोटे उपकरण के बारे में एक अच्छी बात आधुनिक पर्यावरण (नोडजेस और आईई 9 + ब्राउज़र सहित) में है, लौटा हुआ एनम ऑब्जेक्ट अपरिवर्तनीय है।

अधिक जानकारी के लिए कृपया https://github.com/greenlaw110/enumjs चेकआउट https://github.com/greenlaw110/enumjs

अपडेट

मैं gen_enum पैकेज और फ़ंक्शन को constjs पैकेज में विलय करता constjs , जो अपरिवर्तनीय ऑब्जेक्ट्स, JSON स्ट्रिंग deserialization, स्ट्रिंग स्थिरांक और बिटमैप पीढ़ी आदि सहित अधिक सुविधाएं प्रदान करता है। अधिक जानकारी के लिए Checkout constjs

gen_enum से gen_enum अपग्रेड करने के लिए बस कथन बदलें

var genEnum = require('gen_enum');

सेवा मेरे

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

मैंने आंद्रे 'फाई' के समाधान को संशोधित किया है:

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

परीक्षा:

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

यदि आप Backbone का उपयोग कर रहे हैं, तो आप Backbone का उपयोग करके पूर्ण रूप से पूर्ण एनम कार्यक्षमता (आईडी, नाम, कस्टम सदस्यों द्वारा ढूंढें) प्राप्त कर सकते हैं।

// 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()

यह एक पुराना है जिसे मैं जानता हूं, लेकिन जिस तरह से इसे टाइपस्क्रिप्ट इंटरफ़ेस के माध्यम से कार्यान्वित किया गया है वह है:

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

यह आपको MyEnum.Bar दोनों पर देखने में सक्षम बनाता है जो 1, और MyEnum[1] देता है जो घोषणा के आदेश के बावजूद "बार" देता है।


यह वह समाधान है जिसका मैं उपयोग करता हूं।

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

और आप इस तरह अपने enums परिभाषित करते हैं:

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

और इस तरह आप अपने enums तक पहुंचते हैं:

COLORS.BLUE.string
COLORS.BLUE.value
COLORS.getByName('BLUE').string
COLORS.getByValue('value', 1).string

COLORS.forEach(function(e){
    // do what you want with e
});

मैं आमतौर पर संदेश ऑब्जेक्ट्स से मैपिंग मैम के लिए अंतिम 2 विधियों का उपयोग करता हूं।

इस दृष्टिकोण के कुछ फायदे:

  • Enums घोषित करने के लिए आसान है
  • अपने enums तक पहुंचने में आसान है
  • आपके enums जटिल प्रकार हो सकता है
  • अगर आप GetByValue का उपयोग कर रहे हैं तो एनम क्लास में कुछ सहयोगी कैशिंग हैं

कुछ नुकसान:

  • वहां कुछ गन्दा स्मृति प्रबंधन चल रहा है, क्योंकि मैं enums के संदर्भ रखता हूं
  • अभी भी कोई प्रकार की सुरक्षा नहीं है

यहां हम सभी क्या चाहते हैं:

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

अब आप अपने enums बना सकते हैं:

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

ऐसा करके, स्थिरांक को सामान्य तरीके से (YesNo.YES, Color.GREEN) में आकलित किया जा सकता है और उन्हें अनुक्रमिक int मान (NO = 0, YES = 1; RED = 0, GREEN = 1, BLUE = 2) मिलता है।

आप 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 */
};


संपादित करें - छोटे सुधार - अब varargs के साथ: (दुर्भाग्यवश यह IE पर ठीक से काम नहीं करता है: एस ... को पिछले संस्करण के साथ चिपकना चाहिए)

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

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

Simplest solution:

सर्जन करना

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

अद्यतन : सभी उपरोक्त सभी के लिए धन्यवाद, लेकिन मुझे नहीं लगता कि नीचे मेरा जवाब जावास्क्रिप्ट में enums लिखने का सबसे अच्छा तरीका है। अधिक जानकारी के लिए मेरे ब्लॉग पोस्ट देखें: जावास्क्रिप्ट में Enums

नाम को अलर्ट करना पहले से ही संभव है:

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

वैकल्पिक रूप से, आप मूल्य वस्तुओं को बना सकते हैं, ताकि आप केक प्राप्त कर सकें और इसे भी खा सकें:

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

जावास्क्रिप्ट में, क्योंकि यह गतिशील भाषा है, बाद में सेट में enum मान जोड़ना भी संभव है:

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

याद रखें, पहचान जांच के लिए enum के फ़ील्ड (इस उदाहरण में मूल्य, नाम और कोड) की आवश्यकता नहीं है और केवल सुविधा के लिए हैं। इसके अलावा आकार की संपत्ति के नाम को हार्डकोड करने की आवश्यकता नहीं है, लेकिन गतिशील रूप से सेट भी किया जा सकता है। तो आपको लगता है कि आप केवल अपने नए एनम मूल्य के लिए नाम जानते हैं, फिर भी आप इसे बिना किसी समस्या के जोड़ सकते हैं:

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

बेशक इसका मतलब है कि कुछ मान्यताओं को अब नहीं बनाया जा सकता है (वह मान उदाहरण के लिए आकार के सही क्रम का प्रतिनिधित्व करता है)।

याद रखें, जावास्क्रिप्ट में एक वस्तु एक मानचित्र या हैशटेबल की तरह है। नाम-मूल्य जोड़े का एक सेट। आप उनके माध्यम से लूप कर सकते हैं या अन्यथा उनके बारे में बहुत कुछ जानने के बिना उन्हें कुशल बना सकते हैं।

ईजी:

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.        
  }
} 

और बीटीडब्ल्यू, यदि आप नेमस्पेस में दिलचस्पी रखते हैं, तो आप जावास्क्रिप्ट के लिए सरल लेकिन शक्तिशाली नेमस्पेस और निर्भरता प्रबंधन के लिए अपने समाधान को देखना चाहेंगे: पैकेज जेएस


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: string;
    constructor(v: string) {
        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<CellState> {
        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).

update

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 string 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 strict';
    
    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);
    }
    
    toString() {
        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('Untriggered');
    
    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;
    

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 string:int dictionary (an enum).


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

var A = {a:11, b:22}, 
enumA = new TypeHelper(A);

if(enumA.Value === A.b || enumA.Key === "a"){ 
... 
}

var keys = enumA.getAsList();//[object, object]

//set
enumA.setType(22, false);//setType(val, isKey)

enumA.setType("a", true);

enumA.setTypeByIndex(1);

अद्यतन करें:

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.toString() == key.toString()) {
                        _currentType = key;
                    }
                } else if (value && value.toString() == _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, "<br>");


enumA.setType("200L", false);
document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");

enumA.setDefaultType();
document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");


enumA.setTypeByIndex(1);
document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");

document.writeln("is equals = ", (enumA.Value == TypeA["2"]));


es7 way, (iterator, freeze), usage:

const ThreeWiseMen = new Enum('Melchior', 'Caspar', 'Balthazar')

for (let name of ThreeWiseMen)
    console.log(name)


// with a given key
let key = ThreeWiseMen.Melchior

console.log(key in ThreeWiseMen) // true (string conversion, also true: 'Melchior' in ThreeWiseMen)

for (let entry from key.enum)
     console.log(entry)


// prevent alteration (throws TypeError in strict mode)
ThreeWiseMen.Me = 'Me too!'
ThreeWiseMen.Melchior.name = 'Foo'

code:

class EnumKey {

    constructor(props) { Object.freeze(Object.assign(this, props)) }

    toString() { return this.name }

}

export class Enum {

    constructor(...keys) {

        for (let [index, key] of keys.entries()) {

            Object.defineProperty(this, key, {

                value: new EnumKey({ name:key, index, enum:this }),
                enumerable: true,

            })

        }

        Object.freeze(this)

    }

    *[Symbol.iterator]() {

        for (let key of Object.keys(this))
            yield this[key]

    }

    toString() { return [...this].join(', ') }

}





enums