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


2082

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

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

// later on

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

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


131
0गणना संख्या के रूप में उपयोग न करें । जब तक इसका उपयोग किसी ऐसी चीज के लिए नहीं किया जाता जो सेट नहीं की गई है। false || undefined || null || 0 || "" || '' || NaNउपयोग करते समय JS सभी समान मान रखता है ==
मत्सको

152
@matsko == का उपयोग करने के खिलाफ एक तर्क नहीं है?
sdm350

6
0 == nullझूठा लौटाता है
mcont

11
लेकिन false == 0और +null == 0(और संख्या के लिए रूपांतरण कभी कभी जब आप इसे उम्मीद नहीं है हो), जबकि, null == undefinedभी, और +undefinedहै NaN(हालांकि NaN != NaN)।
सैंडर 17

46
डबल समानता मैट्रिक्स माइक्रोसॉफ़्ट शब्द के ऑटो-फॉर्मेटिंग की तुलना में अधिक भ्रामक है
आआआआआआ

जवाबों:


895

1.8.5 के बाद से ऑब्जेक्ट को सील और फ्रीज करना संभव है, इसलिए उपरोक्त को निम्न रूप में परिभाषित करें:

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

या

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

और आवाज! जेएस एनम।

हालाँकि, यह आपको किसी वैरिएबल को अवांछित मान देने से नहीं रोकता है, जो अक्सर एनम का मुख्य लक्ष्य होता है:

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

एक प्रकार की सुरक्षा की एक मजबूत डिग्री सुनिश्चित करने का एक तरीका (एनम के साथ या अन्यथा) जैसे उपकरण का उपयोग करना है एनम के टाइपस्क्रिप्ट या फ्लो

स्रोत

उद्धरण की आवश्यकता नहीं है, लेकिन मैंने उन्हें निरंतरता के लिए रखा।


6
विकिपीडिया ( en.wikipedia.org/wiki/JavaScript#Versions ) के अनुसार यह फ़ायरफ़ॉक्स 4, IE 9, ओपेरा 11.60 पर लागू है और मुझे पता है कि यह क्रोम में काम करता है।
अर्तुर कज्जाका

77
यह 2012 में अब सही उत्तर है। अधिक सरल var DaysEnum = Object.freeze ({ monday: {}, tuesday: {}, ... });:। आपको एक आईडी निर्दिष्ट करने की आवश्यकता नहीं है, आप केवल एक खाली वस्तु का उपयोग कर सकते हैं ताकि आप शत्रुओं की तुलना कर सकें। if (incommingEnum === DaysEnum.monday) //incommingEnum is monday
गेब्रियल ललमास

34
पिछड़ी संगतता के लिए,if (Object.freeze) { Object.freeze(DaysEnum); }
15

17
मैं यह बताना चाहता हूं कि ऐसा करने का ({ monday: {}, अर्थ यह है कि यदि आप उस वस्तु को JSON में परिवर्तित कर देते हैं, तो आपको वह [{"day": {}}]काम मिलेगा जो काम नहीं करने वाला है।
jcollum

10
@Supuhstar इस सवाल के बारे में मेरी राय अब अलग है। फ्रीज () का उपयोग न करें, यह पूरी तरह से बेकार है और "बेवकूफ" चीजें करने में समय की बर्बादी है। यदि आप एक एनम को उजागर करना चाहते हैं, तो बस इसे उजागर करें var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}:। मेरी पिछली टिप्पणी की तरह वस्तुओं की तुलना संख्याओं की तुलना में बहुत अधिक है।
गेब्रियल ललमास

608

यह बहुत जवाब नहीं है, लेकिन मैं कहूंगा कि व्यक्तिगत रूप से ठीक काम करता है

यह कहते हुए कि, चूंकि यह मायने नहीं रखता है कि मान क्या हैं (आपने 0, 1, 2 का उपयोग किया है), मैं उस मामले में एक सार्थक स्ट्रिंग का उपयोग करूँगा जो आप कभी वर्तमान मूल्य का उत्पादन करना चाहते थे।


377
यह एक अन्य उत्तर में कहा गया था, लेकिन चूंकि यह उत्तर स्वीकृत उत्तर है, इसलिए मैं इसे यहां पोस्ट करूंगा। ओपी का हल सही है। यह बेहतर होगा, हालांकि, अगर इसके साथ प्रयोग किया जाता है Object.freeze()। यह अन्य कोड को एनम के मूल्यों को बदलने से रोक देगा। उदाहरण:var ColorEnum = Object.freeze({RED: 0, GREEN: 1, BLUE: 2});
सिल्डोरेथ

5
@ पुस्तकालय उस पुस्तकालय के लिए धन्यवाद! इसने मुझे न केवल इसे न्यूनतम करने के लिए उबालने के लिए प्रेरित किया, बल्कि कुछ विशेषताएं भी जोड़ीं! मैंने तुम्हारा
त्याग

3
@Supuhstar यह बहुत अच्छा है! मुझे खुशी है कि आप इसका उपयोग कर सकते हैं .. एक पुल अनुरोध करने के लिए स्वतंत्र महसूस करें यदि आप चाहते थे कि यह इस पुस्तकालय में विलय हो जाए, तो मैं npm लाइब्रेरी को अपडेट कर सकता हूं
तोलगा ई

2
अगर किसी को दिलचस्पी है, तो मैंने जावा में कैसे हैं, इसके समान टाइप-सुरक्षित एनम लागू किया है। इसका मतलब है कि आप instanceofचेक कर सकते हैं । उदाहरण के लिए ColorEnum.RED instanceof ColorEnum(रिटर्न true)। आप एक नाम ColorEnum.fromName("RED") === ColorEnum.RED(रिटर्न true) से एक उदाहरण भी हल कर सकते हैं । प्रत्येक उदाहरण में .name()एक .ordinal()विधि और एक विधि होती है, और enum में स्वयं एक values()विधि होती है जो सभी स्थिरांक की एक सरणी को पुनः प्राप्त करती है।
विविन पालीथ

3
मुझे यकीन नहीं है कि मैं "सार्थक स्ट्रिंग" सुझाव से सहमत हूं। एनमों को तार या संख्या के रूप में नहीं सोचा जाना चाहिए; वे अमूर्त डेटा प्रकार हैं। कुछ सहायक विधि के बिना "वर्तमान मूल्य को आउटपुट" करना संभव नहीं होना चाहिए। जावा और .NET में, इसकी ToString()विधि है। हम जेएस देवों को पहले से ही "बस काम" करने वाली चीजों पर बहुत अधिक निर्भर करते हैं! इसके अलावा, किसी को switchएनम पर जल्दी से सक्षम होना चाहिए । संख्याओं की तुलना की तुलना में तार की तुलना धीमी है, इसलिए switchयदि आप पूर्णांक के बजाय तार का उपयोग करते हैं तो आपको थोड़ा खराब प्रदर्शन मिलेगा ।
५० पर रबाडा 17२०

501

अपडेट करें

सभी के लिए धन्यवाद सभी को उत्साहित करता है, लेकिन मुझे नहीं लगता कि नीचे दिए गए मेरे जवाब में जावास्क्रिप्ट में एनम लिखने का सबसे अच्छा तरीका है। अधिक जानकारी के लिए मेरा ब्लॉग पोस्ट देखें: जावास्क्रिप्ट में 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);
}

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

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

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


तो यदि आप केवल इसका नाम रखते हैं, तो आप कैसे जाएंगे और केवल एक आकार का निर्माण करेंगे?
जोहानिसमा

2
@Johanisma: यह प्रयोग मामला वास्तव में दुश्मनी के लिए समझ में नहीं आता है क्योंकि उनमें से पूरा विचार यह है कि आप सभी मूल्यों को पहले से जानते हैं। हालाँकि, जावास्क्रिप्ट में बाद में अतिरिक्त मान जोड़ने से आपको कोई रोक नहीं सकता है। मैं अपने उत्तर में इसका एक उदाहरण जोड़ूंगा।
स्टिजन डी विट

2
गुण दृष्टिकोण के साथ अपनी पोस्ट के लिंक के लिए +1। एलपी में, मूल गुण सरल हैं, जैसे कि वांछित होने पर जोड़े गए गुणों के साथ।
गोयडे

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

एक पुस्तकालय भी है जो इसे लागू करता है, साथ ही तुलना और प्रत्यावर्तित खोज के रूप में अच्छी विशेषताएं भी शामिल है: github.com/adrai/enum
रोमन एम।

83

नीचे पंक्ति: आप नहीं कर सकते।

आप इसे नकली कर सकते हैं, लेकिन आपको टाइप सुरक्षा नहीं मिलेगी। आमतौर पर यह पूर्णांक मानों के लिए मैप किए गए स्ट्रिंग मानों का एक सरल शब्दकोश बनाकर किया जाता है। उदाहरण के लिए:

var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}

Document.Write("Enumerant: " + DaysEnum.tuesday);

इस दृष्टिकोण के साथ समस्या? आप गलती से अपने एन्यूमरेंट को फिर से परिभाषित कर सकते हैं, या गलती से डुप्लिकेट एन्यूमरेंट मान हो सकते हैं। उदाहरण के लिए:

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

संपादित करें

Artur Czajka के ऑब्जेक्ट के बारे में। क्या यह काम आपको सोमवार से लेकर थर्सडे तक सेट करने से नहीं रोकेगा? - फ्राई क्वाड

बिल्कुल, Object.freezeपूरी तरह से मेरे द्वारा शिकायत की गई समस्या को ठीक कर देगा। मैं सभी को याद दिलाना चाहूंगा कि जब मैंने ऊपर लिखा Object.freezeथा , तो वास्तव में मौजूद नहीं था।

अब .... अब यह कुछ बहुत ही दिलचस्प संभावनाओं को खोलता है।

संपादित करें 2
यहाँ पर एनमोंस बनाने के लिए बहुत अच्छी लाइब्रेरी है।

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

हालांकि यह संभवतः एनम के हर वैध उपयोग के लायक नहीं है, यह बहुत लंबा रास्ता तय करता है।


103
जावास्क्रिप्ट में टाइप सुरक्षा है?
स्कॉट एवरंडन

3
इसलिए ऑब्जेक्ट के गुणों के लिए मानों को मैप न करें। प्रवेशक का उपयोग करने के लिए गेटर का उपयोग करें (एक संपत्ति के रूप में संग्रहीत, कहते हैं, "निजी" ऑब्जेक्ट)। एक भोली कार्यान्वयन की तरह दिखेगा -var daysEnum = (function(){ var daysEnum = { monday: 1, tuesday: 2 }; return { get: function(value){ return daysEnum[value]; } } })(); daysEnum.get('monday'); // 1
kangax

2
@ सॉट एवरंडन: बिंदु को लिया गया। @ भांग: बिंदु यह है कि यह अभी भी एक हैक है। एनवेस बस जावास्क्रिप्ट में मौजूद नहीं है, अवधि, कहानी का अंत। यहां तक ​​कि टिम सिल्वेस्टर द्वारा सुझाए गए पैटर्न अभी भी आदर्श हैक से कम है।
रैंडोल्फो

2
कोड को शाब्दिक रूप से छिड़कना बहुत अनुरक्षण नहीं है, इसलिए यह इसके लिए स्थिरांक बनाने के लिए समझ में आता है। बेशक जावास्क्रिप्ट में कोई स्थिरांक नहीं है। तो मूल रूप से यह साफ कोड लिखने का एक तरीका है। इसे लागू नहीं किया जा सकता है, लेकिन जावास्क्रिप्ट में बहुत अधिक नहीं हो सकता है। आप स्थिरांक, या फ़ंक्शंस, या अधिकतर कुछ भी पुनः परिभाषित कर सकते हैं। ईजी: document.getElementById = function () {अलर्ट ("आप खराब हो गए हैं। जावास्क्रिप्ट प्रकार नहीं है।");};
स्टिजन डे विट

3
@ रैंडोल्फ: अर्तुर कज्जाका के ऑब्जेक्ट के बारे में। क्या यह काम आपको सोमवार से लेकर थर्सडे तक सेट करने से नहीं रोकेगा?
माइकल - कहाँ है क्ले Shirky

56

यहाँ हम क्या चाहते हैं:

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

अब आप अपनी दुश्मनी बना सकते हैं:

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 पर ठीक से काम नहीं करता है: S ... फिर पिछले संस्करण के साथ रहना चाहिए)

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

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

इस उत्तर की सादगी से प्यार करें!
मार्क्विजो

@Marquizzo (और OP) मैंने इस उत्तर के आधार पर एक बेहतर संस्करण बनाया: stackoverflow.com/a/60309416/1599699
एंड्रयू

53

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

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

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

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

यह सिद्धांत में सही उत्तर है। व्यवहार में, 2015 ब्राउज़र समर्थन पर्याप्त से दूर है। अब तक तैयार नहीं हुआ उत्पादन।
वबुन

1
हालांकि ब्राउज़र समर्थन अभी तक नहीं है, लेकिन यह सबसे अच्छा जवाब है क्योंकि यह वही Symbolहै जो इसके लिए इरादा है।
रेवन्ने

2
मेह ... Enum मानों को अक्सर क्रमबद्ध होने की आवश्यकता होती है, और Symbols को क्रमबद्ध और अस्वाभाविक बनाने के लिए इतना आसान नहीं होता है।
एंडी

3
क्या यह सिर्फ मैं या Object.freezeकेवल उन लोगों के लिए है जिन्होंने इस तथ्य को स्वीकार नहीं किया है कि "अपने जोखिम पर बंदर पकड़ने" जेएस का सामाजिक अनुबंध है?
एंडी

@ और हां सीरियलाइजेशन कष्टप्रद है। मैं toJSONइस दृष्टिकोण का उपयोग करने के लिए युक्त वर्ग पर एक स्पष्ट कर रहा हूं : stackoverflow.com/questions/58499828/…
Ciro Santilli 冠状 explicit explicit 事件

30

𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲 𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲 𝗣𝗹𝗮𝗶𝗻 𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲

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


wvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwv

अंडरस्कोर-संकेतन चर

जैसा कि ऊपर दिए गए चार्ट में दिखाया गया है और नीचे दिए गए उदाहरण हैं, शुरू करने के लिए यहां पांच आसान चरण दिए गए हैं:

  1. गणना समूह के लिए एक नाम निर्धारित करें। एक संज्ञा के बारे में सोचें जो गणना के उद्देश्य या कम से कम प्रविष्टियों में वर्णन कर सकती है। उदाहरण के लिए, उपयोगकर्ता द्वारा चयन किए जाने वाले रंगों का प्रतिनिधित्व करने वाले गणन का एक समूह रंग से बेहतर रंग के नाम हो सकता है।
  2. तय करें कि क्या समूह में गणना परस्पर-अनन्य या स्वतंत्र है। यदि पारस्परिक रूप से अनन्य है, तो प्रत्येक नामांकित चर नाम के साथ शुरू करें ENUM_। यदि स्वतंत्र या साइड-बाय-साइड, उपयोग करें INDEX_
  3. प्रत्येक प्रविष्टि के लिए, एक नया स्थानीय वैरिएबल बनाएं, जिसका नाम शुरू होता है ENUM_या INDEX_फिर समूह का नाम, फिर एक अंडरस्कोर, फिर संपत्ति के लिए एक अद्वितीय अनुकूल नाम
  4. एक जोड़े ENUMLENGTH_, ENUMLEN_, INDEXLENGTH_, या INDEXLEN_(चाहे LEN_या LENGTH_बहुत अंत में है व्यक्तिगत पसंद) प्रगणित चर। आपको अपने कोड में जहां भी संभव हो, इस चर का उपयोग यह सुनिश्चित करने के लिए करना चाहिए कि गणन में एक अतिरिक्त प्रविष्टि जोड़ने और इस मूल्य को बढ़ाने से आपका कोड नहीं टूटेगा।
  5. लगातार प्रत्येक enumerated चर एक मूल्य के एक आखिरी की तुलना में अधिक दो, 0. पर शुरू इस पेज पर टिप्पणी है कि कहते हैं कर रहे हैं 0एक प्रगणित मूल्य क्योंकि के रूप में नहीं किया जाना चाहिए 0 == null, 0 == false, 0 == "", और अन्य जे एस पागलपन। मैं आपको इस समस्या से बचने और एक ही समय में प्रदर्शन को बढ़ावा देने के लिए प्रस्तुत करता हूं, हमेशा उपयोग करें ===और कभी भी ==अपने कोड में प्रकट न करें typeof(पूर्व typeof X == "string") को छोड़कर । उपयोग करने के अपने सभी वर्षों में ===, मुझे कभी भी 0 का गणना मूल्य के रूप में उपयोग करने में कोई समस्या नहीं हुई। यदि आप अभी भी बग़ल में हैं, तो कई मामलों में प्रदर्शन जुर्माना के बिना गणना 1में ENUM_गणना मूल्य (लेकिन INDEX_गणना में नहीं ) के रूप में इस्तेमाल किया जा सकता है ।
const ENUM_COLORENUM_RED   = 0;
const ENUM_COLORENUM_GREEN = 1;
const ENUM_COLORENUM_BLUE  = 2;
const ENUMLEN_COLORENUM    = 3;

// later on

if(currentColor === ENUM_COLORENUM_RED) {
   // whatever
}

यहाँ बताया गया है कि मुझे याद है कि कब उपयोग करना है INDEX_और कब उपयोग करना है ENUM_:

// Precondition: var arr = []; //
arr[INDEX_] = ENUM_;

हालांकि, ENUM_कुछ परिस्थितियों में, सूचकांक के रूप में उपयुक्त हो सकता है जैसे कि प्रत्येक आइटम की घटनाओं को गिनते समय।

const ENUM_PET_CAT = 0,
      ENUM_PET_DOG = 1,
      ENUM_PET_RAT = 2,
      ENUMLEN_PET  = 3;

var favoritePets = [ENUM_PET_CAT, ENUM_PET_DOG, ENUM_PET_RAT,
                    ENUM_PET_DOG, ENUM_PET_DOG, ENUM_PET_CAT,
                    ENUM_PET_RAT, ENUM_PET_CAT, ENUM_PET_DOG];

var petsFrequency = [];

for (var i=0; i<ENUMLEN_PET; i=i+1|0)
  petsFrequency[i] = 0;

for (var i=0, len=favoritePets.length|0, petId=0; i<len; i=i+1|0)
  petsFrequency[petId = favoritePets[i]|0] = (petsFrequency[petId]|0) + 1|0;

console.log({
    "cat": petsFrequency[ENUM_PET_CAT],
    "dog": petsFrequency[ENUM_PET_DOG],
    "rat": petsFrequency[ENUM_PET_RAT]
});

गौर करें कि, ऊपर दिए गए कोड में, नए प्रकार के पालतू जानवरों को जोड़ना वास्तव में आसान है: आपको बस एक नई प्रविष्टि संलग्न करनी होगी ENUM_PET_RATऔर उसके ENUMLEN_PETअनुसार अपडेट करना होगा । गणना की अन्य प्रणालियों में एक नई प्रविष्टि जोड़ने के लिए यह अधिक कठिन और छोटी बात हो सकती है।


wvwwvw wvwwww wvwxvw wvwvwv vwvwvw wvwvvw wvwwvw wvwvww wvwvw wvwvwv vwvxwv wvwvw wvwvw wvwvwwvvwwwvw

𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲𝘀 𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲𝘀 𝗘𝘅𝘁𝗲𝗻𝗱 𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲𝘀 𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲𝘀

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

जोड़ विस्तार आरेख

(function(window){
    "use strict";
    var parseInt = window.parseInt;

    // use INDEX_ when representing the index in an array instance
    const INDEX_PIXELCOLOR_TYPE = 0, // is a ENUM_PIXELTYPE
          INDEXLEN_PIXELCOLOR   = 1,
          INDEX_SOLIDCOLOR_R    = INDEXLEN_PIXELCOLOR+0,
          INDEX_SOLIDCOLOR_G    = INDEXLEN_PIXELCOLOR+1,
          INDEX_SOLIDCOLOR_B    = INDEXLEN_PIXELCOLOR+2,
          INDEXLEN_SOLIDCOLOR   = INDEXLEN_PIXELCOLOR+3,
          INDEX_ALPHACOLOR_R    = INDEXLEN_PIXELCOLOR+0,
          INDEX_ALPHACOLOR_G    = INDEXLEN_PIXELCOLOR+1,
          INDEX_ALPHACOLOR_B    = INDEXLEN_PIXELCOLOR+2,
          INDEX_ALPHACOLOR_A    = INDEXLEN_PIXELCOLOR+3,
          INDEXLEN_ALPHACOLOR   = INDEXLEN_PIXELCOLOR+4,
    // use ENUM_ when representing a mutually-exclusive species or type
          ENUM_PIXELTYPE_SOLID = 0,
          ENUM_PIXELTYPE_ALPHA = 1,
          ENUM_PIXELTYPE_UNKNOWN = 2,
          ENUMLEN_PIXELTYPE    = 2;

    function parseHexColor(inputString) {
        var rawstr = inputString.trim().substring(1);
        var result = [];
        if (rawstr.length === 8) {
            result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_ALPHA;
            result[INDEX_ALPHACOLOR_R] = parseInt(rawstr.substring(0,2), 16);
            result[INDEX_ALPHACOLOR_G] = parseInt(rawstr.substring(2,4), 16);
            result[INDEX_ALPHACOLOR_B] = parseInt(rawstr.substring(4,6), 16);
            result[INDEX_ALPHACOLOR_A] = parseInt(rawstr.substring(4,6), 16);
        } else if (rawstr.length === 4) {
            result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_ALPHA;
            result[INDEX_ALPHACOLOR_R] = parseInt(rawstr[0], 16) * 0x11;
            result[INDEX_ALPHACOLOR_G] = parseInt(rawstr[1], 16) * 0x11;
            result[INDEX_ALPHACOLOR_B] = parseInt(rawstr[2], 16) * 0x11;
            result[INDEX_ALPHACOLOR_A] = parseInt(rawstr[3], 16) * 0x11;
        } else if (rawstr.length === 6) {
            result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_SOLID;
            result[INDEX_SOLIDCOLOR_R] = parseInt(rawstr.substring(0,2), 16);
            result[INDEX_SOLIDCOLOR_G] = parseInt(rawstr.substring(2,4), 16);
            result[INDEX_SOLIDCOLOR_B] = parseInt(rawstr.substring(4,6), 16);
        } else if (rawstr.length === 3) {
            result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_SOLID;
            result[INDEX_SOLIDCOLOR_R] = parseInt(rawstr[0], 16) * 0x11;
            result[INDEX_SOLIDCOLOR_G] = parseInt(rawstr[1], 16) * 0x11;
            result[INDEX_SOLIDCOLOR_B] = parseInt(rawstr[2], 16) * 0x11;
        } else {
            result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_UNKNOWN;
        }
        return result;
    }

    // the red component of green
    console.log(parseHexColor("#0f0")[INDEX_SOLIDCOLOR_R]);
    // the alpha of transparent purple
    console.log(parseHexColor("#f0f7")[INDEX_ALPHACOLOR_A]); 
    // the enumerated array for turquoise
    console.log(parseHexColor("#40E0D0"));
})(self);

(लंबाई: 2,450 बाइट्स)

कुछ लोग कह सकते हैं कि यह अन्य समाधानों की तुलना में कम व्यावहारिक है: यह टन अंतरिक्ष की प्रतीक्षा करता है, इसे लिखने में लंबा समय लगता है, और यह चीनी सिंटैक्स के साथ लेपित नहीं है। यदि वे अपने कोड को छोटा नहीं करते हैं तो वे लोग सही होंगे। हालांकि, कोई भी उचित व्यक्ति अंतिम उत्पाद में अनधिकृत कोड नहीं छोड़ेगा। इस लघुकरण के लिए, क्लोजर कंपाइलर सबसे अच्छा है जो मुझे अभी तक ढूंढना है। ऑनलाइन एक्सेस यहां पाया जा सकता है । क्लोजर कंपाइलर इस एन्यूमरेशन डेटा के सभी को लेने और इसे इनलाइन करने में सक्षम है, जिससे आपका जावास्क्रिप्ट सुपर डुपर छोटा और सुपर डुपर फास्ट रन करेगा। इस प्रकार, क्लोजर कंपाइलर के साथ न्यूनतम करें। ध्यान से देखें।


wvwwvw wvwwww wvwxvw wvwvwv vwvwvw wvwvvw wvwwvw wvwvww wvwvw wvwvwv vwvxwv wvwvw wvwvw wvwvwwvvwwwvw

𝗖𝗹𝗼𝘀𝘂𝗿𝗲 𝗖𝗹𝗼𝘀𝘂𝗿𝗲 𝗠𝗶𝗻𝗶𝗳𝘆 𝗖𝗹𝗼𝘀𝘂𝗿𝗲

क्लोजर कंपाइलर कुछ अविश्वसनीय अविश्वसनीय अनुकूलन प्रदर्शनों के माध्यम से करने में सक्षम है जो किसी अन्य जावास्क्रिप्ट मिनिफ़ायर की क्षमताओं से परे हैं। क्लोजर कंपाइलर एक निश्चित मान पर सेट आदिम वैरिएबल को इनलाइन करने में सक्षम है। क्लोजर कंपाइलर इन-इन वैल्यू के आधार पर इनफेक्शन बनाने में सक्षम है और अगर-स्टेटमेंट और लूप में अप्रयुक्त ब्लॉक को खत्म करता है।

क्लोजर कंपाइलर के माध्यम से कोडिंग कोड

'use strict';(function(e){function d(a){a=a.trim().substring(1);var b=[];8===a.length?(b[0]=1,b[1]=c(a.substring(0,2),16),b[2]=c(a.substring(2,4),16),b[3]=c(a.substring(4,6),16),b[4]=c(a.substring(4,6),16)):4===a.length?(b[1]=17*c(a[0],16),b[2]=17*c(a[1],16),b[3]=17*c(a[2],16),b[4]=17*c(a[3],16)):6===a.length?(b[0]=0,b[1]=c(a.substring(0,2),16),b[2]=c(a.substring(2,4),16),b[3]=c(a.substring(4,6),16)):3===a.length?(b[0]=0,b[1]=17*c(a[0],16),b[2]=17*c(a[1],16),b[3]=17*c(a[2],16)):b[0]=2;return b}var c=
e.parseInt;console.log(d("#0f0")[1]);console.log(d("#f0f7")[4]);console.log(d("#40E0D0"))})(self);

(लंबाई: 605 बाइट्स)

क्लोजर कंपाइलर आपको बेहतर कोडिंग के लिए पुरस्कृत करता है और आपके कोड को अच्छी तरह से व्यवस्थित करता है, क्योंकि कई मिनिफ़ाइर एक बड़े आकार की फ़ाइल आकार के साथ संगठित कोड को सज़ा देते हैं, क्लोजर कंपाइलर आपके सभी स्वच्छता और विवेक के माध्यम से झारना करने में सक्षम है, यदि आप ट्रिक्स का उपयोग करते हैं चर नाम गणना की तरह। यह, इस एक दिमाग में, कोडिंग की पवित्र कब्र है: एक उपकरण जो दोनों आपके कोड को छोटे आकार के आकार के साथ सहायता करता है और बेहतर प्रोग्रामिंग आदतों को प्रशिक्षित करके आपके दिमाग को सहायता प्रदान करता है।


wvwwvw wvwwww wvwxvw wvwvwv vwvwvw wvwvvw wvwwvw wvwvww wvwvw wvwvwv vwvxwv wvwvw wvwvw wvwvwwvvwwwvw

𝗦𝗶𝘇𝗲 𝗦𝗶𝘇𝗲 𝗦𝗶𝘇𝗲

अब, देखते हैं कि इनमें से किसी भी गणना के बिना समतुल्य फ़ाइल कितनी बड़ी होगी।

Enumerations का उपयोग किए बिना स्रोत (लंबाई: 1,973 बाइट्स (477 बाइट्स enumerated कोड से छोटा है!))
Enumerations (लंबाई: 843 बाइट्स ( enumerated कोड से अधिक लंबे बाइट्स ) का उपयोग किए बिना छोटा किया गया )

कोड आकार का चार्ट



जैसा कि देखा गया है, गणना के बिना, स्रोत कोड एक बड़े कीम कोड की कीमत पर छोटा होता है। मुझे आपके बारे में कुछ पता नही है; लेकिन मुझे पता है कि मैं अंत उत्पाद में स्रोत कोड को शामिल नहीं करता हूं। इस प्रकार, गणना का यह रूप बहुत बेहतर है कि छोटे फ़ाइल आकार में परिणाम हो।


wvwwvw wvwwww wvwxvw wvwvwv vwvwvw wvwvvw wvwwvw wvwvww wvwvw wvwvwv vwvxwv wvwvw wvwvw wvwvwwvvwwwvw

𝗕𝘂𝗴 𝗕𝘂𝗴 𝗖𝗼𝗼𝗽𝗲𝗿𝗮𝘁𝗶𝘃𝗲 𝗕𝘂𝗴

गणन के इस रूप के बारे में एक और लाभ यह है कि इसका उपयोग आसानी से बड़े आकार की परियोजनाओं को प्रबंधित करने के लिए किया जा सकता है, जो बिना किसी आकार के कोड आकार का त्याग किए। जब कई अन्य लोगों के साथ एक बड़ी परियोजना पर काम कर रहे हैं, तो यह स्पष्ट रूप से लाभदायक हो सकता है कि कोड बनाने वाले चर नामों को स्पष्ट रूप से चिह्नित करें और लेबल करें ताकि कोड के मूल निर्माता को जल्दी से सहयोगी बग फिक्सिंग के लिए पहचाना जा सके।

// JG = Jack Giffin
const ENUM_JG_COLORENUM_RED   = 0,
      ENUM_JG_COLORENUM_GREEN = 1,
      ENUM_JG_COLORENUM_BLUE  = 2,
      ENUMLEN_JG_COLORENUM    = 3;

// later on

if(currentColor === ENUM_JG_COLORENUM_RED) {
   // whatever
}

// PL = Pepper Loftus
// BK = Bob Knight
const ENUM_PL_ARRAYTYPE_UNSORTED   = 0,
      ENUM_PL_ARRAYTYPE_ISSORTED   = 1,
      ENUM_BK_ARRAYTYPE_CHUNKED    = 2, // added by Bob Knight
      ENUM_JG_ARRAYTYPE_INCOMPLETE = 3, // added by jack giffin
      ENUMLEN_PL_COLORENUM         = 4;

// later on

if(
  randomArray === ENUM_PL_ARRAYTYPE_UNSORTED ||
  randomArray === ENUM_BK_ARRAYTYPE_CHUNKED
) {
   // whatever
}

𝗦𝘂𝗽𝗲𝗿𝗶𝗼𝗿 𝗦𝘂𝗽𝗲𝗿𝗶𝗼𝗿

इसके अलावा, गणना के बाद इस तरह की गणना भी तेजी से होती है। सामान्य नाम वाली संपत्तियों में, ब्राउज़र को यह देखने के लिए हैशमैप का उपयोग करना पड़ता है कि संपत्ति ऑब्जेक्ट पर कहाँ है। यद्यपि JIT इस स्थान को समझदारी से कैश करने के लिए मजबूर करता है, लेकिन विशेष मामलों जैसे ऑब्जेक्ट से कम संपत्ति को हटाने के कारण अभी भी जबरदस्त ओवरहेड है।

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

/// Hashmaps are slow, even with JIT juice
var ref = {};
ref.count = 10;
ref.value = "foobar";

नीचे दिए गए कोड की तुलना कोड से करें।

/// Arrays, however, are always lightning fast
const INDEX_REFERENCE_COUNT = 0;
const INDEX_REFERENCE_VALUE = 1;
const INDEXLENGTH_REFERENCE = 2;

var ref = [];
ref[INDEX_REFERENCE_COUNT] = 10;
ref[INDEX_REFERENCE_VALUE] = "foobar";

एक कोड के साथ आपत्ति कर सकते हैं गणना सामान्य वस्तुओं के साथ कोड की तुलना में अधिक लंबा लग रहा है, लेकिन लगता है कि धोखा हो सकता है। यह याद रखना महत्वपूर्ण है कि महाकाव्य बंद करने वाले कंपाइलर का उपयोग करते समय स्रोत कोड का आकार आउटपुट आकार के लिए आनुपातिक नहीं है। ध्यान से देखें।

/// Hashmaps are slow, even with JIT juice
var a={count:10,value:"foobar"};

एन्यूमरेशंस के बिना मिनिमाइज्ड कोड ऊपर है और एन्युमेरेशंस वाला मिनिफाईड कोड नीचे है।

/// Arrays, however, are always lightning fast
var a=[10,"foobar"];

ऊपर दिए गए उदाहरण से पता चलता है कि, बेहतर प्रदर्शन करने के अलावा, एन्यूमरेटेड कोड के परिणामस्वरूप छोटे आकार का फ़ाइल आकार भी होता है।


wvwwvw wvwwww wvwxvw wvwvwv vwvwvw wvwvvw wvwwvw wvwvww wvwvw wvwvwv vwvxwv wvwvw wvwvw wvwvwwvvwwwvw

𝗘𝗮𝘀𝘆 𝗘𝗮𝘀𝘆

इसके अलावा, शीर्ष पर यह किसी की निजी चेरी जावास्क्रिप्ट स्क्रिप्ट में कोडमिरर टेक्स्ट एडिटर के साथ एन्यूमरेशन के इस रूप का उपयोग कर रही है। कोडमिरर का जावास्क्रिप्ट सिंटैक्स हाइलाइटिंग मोड वर्तमान चर में स्थानीय चरों को हाइलाइट करता है। इस तरह, आप तुरंत जानते हैं जब आप एक चर नाम में सही ढंग से लिखते हैं क्योंकि अगर चर नाम पहले साथ घोषित किया गया थाvar कीवर्ड के , तो चर नाम एक विशेष रंग (डिफ़ॉल्ट रूप से सियान) में बदल जाता है। यहां तक ​​कि अगर आप कोडमिरर का उपयोग नहीं करते हैं, तो कम से कम ब्राउज़र एक सहायक फेंकता है[variable name] is not definedजब कोड को गलत संकलित नामों के साथ निष्पादित किया जाता है। इसके अलावा, जावास्क्रिप्ट उपकरण जैसे कि JSLint और क्लोजर कंपाइलर आपको यह बताने के बारे में बहुत जोर से कहते हैं कि जब आप किसी गणन चर नाम में गलती करते हैं। CodeMirror, ब्राउज़र, और विभिन्न जावास्क्रिप्ट उपकरण एक साथ रखे हुए इस रूप को बहुत सरल और वास्तव में आसान बनाते हैं।

कोडमिरर प्रदर्शन पर प्रकाश डालते हुए

const ENUM_COLORENUM_RED   = 0,
      ENUM_COLORENUM_GREEN = 1,
      ENUM_COLORENUM_BLUE  = 2,
      ENUMLEN_COLORENUM    = 3;
var currentColor = ENUM_COLORENUM_GREEN;

if(currentColor === ENUM_COLORENUM_RED) {
   // whatever
}

if(currentColor === ENUM_COLORENUM_DNE) {
   // whatever
}

उपरोक्त स्निपेट में, आपको एक त्रुटि के साथ अलर्ट किया गया था क्योंकि ENUM_COLORENUM_DNEमौजूद नहीं है।


wvwwvw wvwwww wvwxvw wvwvwv vwvwvw wvwvvw wvwwvw wvwvww wvwvw wvwvwv vwvxwv wvwvw wvwvw wvwvwwvvwwwvw

𝗖𝗼𝗻𝗰𝗹𝘂𝘀𝗶𝗼𝗻 𝗖𝗼𝗻𝗰𝗹𝘂𝘀𝗶𝗼𝗻

मुझे लगता है कि यह कहना सुरक्षित है कि गणना की यह कार्यप्रणाली वास्तव में न केवल न्यूनतम आकार के लिए, बल्कि प्रदर्शन, डिबगिंग और सहयोग के लिए भी जाने का सबसे अच्छा तरीका है।

एक सहायक प्रश्न पढ़ने के बाद, मैं लेखक को प्रश्न बॉक्स में शीर्ष बाएं ऊपर-तीर पर क्लिक करके उनके लेखन में समय डालने के लिए धन्यवाद देता हूं। प्रत्येक उत्तर बॉक्स में भी इनमें से एक है।


एह। मैं दृढ़ता से पठनीयता और उपयोग में आसानी और कोड आकार को समझना पसंद करता हूं।
एंड्रयू

1
@ और मेरे उत्तर के साथ, आप दोनों हो सकते हैं। उपयोग के लिए सबसे आसान में मेरा जवाब परिणाम / कोड का प्रबंधन और छोटी से छोटी minified कोड size.🙂 में
जैक Giffin

1
@ और मैंने अपने उत्तर में रंग पार्सर उदाहरण के लिए आपका येट एनम (YEA!) लागू करने का प्रयास किया है । हालाँकि, मुझे कई समस्याएं मिली हैं जिन्हें आप दूर करना चाहते हैं। YEA के पास उपवर्गों के साथ गणना का विस्तार करने का कोई तरीका नहीं है, जिससे मुझे अलग-अलग अभिभावक और बाल वर्ग बनाने के लिए मजबूर होना पड़ता है, जो बड़ी परियोजनाओं पर प्रबंधन करने के लिए काफी कठिन हो सकता है। YEA यह सुनिश्चित नहीं करता है कि प्रविष्टि मौजूद है (पूर्व colors.REEDपैदावार undefined), इसलिए टाइपोस मायावी conundrums बनाते हैं। YEA एन्यूमेरेशंस के इंडेक्स और आईडी के उपयोग के बीच अंतर नहीं करता है, जिससे भ्रामक कोड हो जाता है जहां सब कुछ समान दिखता है। …
जैक गिफिन

1
@ और ... YEA क्लोजर कंपाइलर की क्षमता को कम करने में बाधा डालती है। मेरे कोड (604 बाइट्स) के साथ स्रोत कोड की तुलना YEA (3549 बाइट्स) के साथ मिनिफ़ाइस्ड कोड YEA (1344 बाइट्स) के साथ करें। अंत में, YEA में "नाम से मानचित्रण" शामिल है, क्योंकि यह स्ट्रिंग नामों को एन्यूमरेटेड आईडी से अलग करता है। मेरा केवल आईडी मानता है, इसलिए "नाम से मैपिंग" की आवश्यकता नहीं है, सरल डिजाइन और बेहतर प्रदर्शन के लिए अग्रणी। अपना समाधान साझा करने के लिए धन्यवाद, लेकिन व्यावहारिक होने से पहले इसे कई सुधारों की आवश्यकता होती है।
जैक गिफिन

1
@ और आप अपनी राय के हकदार हैं क्योंकि मैं मेरा 👍 हूं
जैक गिफिन

23

मैं इस के साथ चारों ओर खेल रहा हूं, जैसा कि मुझे अपनी दुश्मनी से प्यार है। =)

का उपयोग करते हुए 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इस करना चाहिए यह सुरक्षित टाइप कर सकते हैं।

तो आपको एक कस्टम ऑब्जेक्ट बनाने में सक्षम होना चाहिए, फिर उस Enum()पर कॉल करें । असाइन किए गए मान 0 पर शुरू होते हैं और प्रति आइटम वेतन वृद्धि होती है।

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

3
यदि आप return this;Enum के अंत में जोड़ते हैं तो आप कर सकते हैं:var EnumColors = {}.Enum('RED','BLUE','GREEN','YELLOW');
HBP

मैं ऐसा नहीं मानता था, क्योंकि यह मेरे काम करने का सामान्य तरीका नहीं है। लेकिन आप बिल्कुल सही हैं! मैं इसे संपादित करूंगा।
डंकन

मैं वास्तव में इसे पसंद करता हूं, हालांकि मैं ऑब्जेक्ट स्पेस (ग्लोबल फंक्शन ENUM के साथ) को मिलाने का बहुत बड़ा प्रशंसक नहीं हूं। इसे एक म्यूकेनम फ़ंक्शन में रूपांतरित किया और वैकल्पिक संख्यात्मक असाइनमेंट्स => var मिश्रित यूपी = mkenum ('BLACK', {RED: 0x0F00, BLUE: 0X0F, GREEN: 0x0F0, WHITE: 0x0FFF, ONE: 1: TWO, THREE, FOUR) ; // नीचे एक उत्तर के रूप में मेरा कोड जोड़ना। धन्यवाद।
एंड्रयू फिलिप्स

सच कहूं तो, मैं अब भी इसका इस्तेमाल नहीं करता हूं। मैं Google के क्लोजर कंपाइलर का उपयोग कर रहा हूं, और यदि आप उन्नत सेटिंग का उपयोग करते हैं, तो यह बहुत अच्छी तरह से काम नहीं करता है (या यह सिर्फ चीजों को जटिल करता है)। तो मैं बस मानक वस्तु संकेतन पर वापस चला गया हूं।
डंकन

1
falseके लिए डिफ़ॉल्ट है writable, enumerableऔर configurable। चूक पर चबाने की कोई जरूरत नहीं है।
छत

23

जावास्क्रिप्ट प्रॉक्सी का उपयोग करें

TLDR: इस क्लास को अपने यूटिलिटी मेथड्स में जोड़ें और अपने पूरे कोड में इसका इस्तेमाल करें, यह पारंपरिक प्रोग्रामिंग लैंग्वेज से Enum बिहेवियर को मॉक करता है, और वास्तव में एरर को एक्सेस करने या एनुमरेट करने या अपडेट करने वाले को एक्सेस करने की कोशिश करने पर एरर फेंकता है। भरोसा करने की जरूरत नहीं Object.freeze()

class Enum {
  constructor(enumObj) {
    const handler = {
      get(target, name) {
        if (typeof target[name] != 'undefined') {
          return target[name];
        }
        throw new Error(`No such enumerator: ${name}`);
      },
      set() {
        throw new Error('Cannot add/update properties on an Enum instance after it is defined')
      }
    };

    return new Proxy(enumObj, handler);
  }
}

फिर कक्षा को तत्काल लगाकर एनम बनाएं:

const roles = new Enum({
  ADMIN: 'Admin',
  USER: 'User',
});

पूर्ण व्याख्या:

एनमों की एक बहुत ही लाभदायक विशेषता जो आपको पारंपरिक भाषाओं से मिलती है, वह यह है कि यदि आप किसी एन्यूमरेटर तक पहुंचने का प्रयास करते हैं, तो वे उड़ जाते हैं (संकलन-समय की त्रुटि फेंक देते हैं)।

गलती से / दुर्भावनापूर्ण रूप से अतिरिक्त मान को रोकने के लिए नकली एनुम संरचना को ठंड के अलावा, अन्य उत्तरों में से कोई भी पता नहीं है जो एनम की आंतरिक विशेषता है।

जैसा कि आप शायद जानते हैं, जावास्क्रिप्ट में गैर-मौजूदा सदस्यों तक पहुंच बस वापस आती है undefinedऔर आपके कोड को उड़ा नहीं देती है। चूंकि एन्यूमरेटर पूर्वनिर्धारित स्थिरांक (सप्ताह के दिन) हैं, इसलिए कभी भी ऐसा मामला नहीं होना चाहिए जब किसी एन्यूमरेटर को अपरिभाषित किया जाए।

मुझे गलत मत समझिए, undefinedअपरिभाषित गुणों तक पहुँचने पर जावास्क्रिप्ट का वापस लौटने का व्यवहार वास्तव में भाषा की एक बहुत शक्तिशाली विशेषता है, लेकिन जब आप पारंपरिक एनम संरचनाओं का मजाक उड़ाने की कोशिश कर रहे हैं तो यह ऐसी सुविधा नहीं है जो आप चाहते हैं।

यह वह जगह है जहाँ प्रॉक्सी ऑब्जेक्ट चमकते हैं। ES6 (ES2015) की शुरुआत के साथ भाषा में प्रॉक्सी का मानकीकरण किया गया था। यहाँ MDN से विवरण है:

प्रॉक्सी ऑब्जेक्ट का उपयोग मूलभूत कार्यों (जैसे संपत्ति देखने, असाइनमेंट, एन्यूमरेशन, फंक्शन इनवोकेशन, आदि) के लिए कस्टम व्यवहार को परिभाषित करने के लिए किया जाता है।

एक वेब सर्वर प्रॉक्सी के समान, जावास्क्रिप्ट प्रॉक्सी वस्तुओं ("ट्रैप्स" के उपयोग के साथ संचालन को बाधित करने में सक्षम हैं, यदि आप चाहें तो उन्हें हुक कहते हैं) और आपको पूर्ण होने से पहले (या,) विभिन्न जांच, क्रिया और / या हेरफेर करने की अनुमति देते हैं (या कुछ मामलों में परिचालन को पूरी तरह से रोकना जो कि वास्तव में हम क्या करना चाहते हैं अगर हम एक एन्यूमरेटर को संदर्भित करने का प्रयास करते हैं जो मौजूद नहीं है)।

यहाँ एक काल्पनिक उदाहरण है जो Enums की नकल करने के लिए प्रॉक्सी ऑब्जेक्ट का उपयोग करता है। इस उदाहरण में प्रगणक मानक HTTP तरीके हैं (जैसे "GET", "POST", आदि):

// Class for creating enums (13 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 transpile using a service like babel

class Enum {
  // The Enum class instantiates a JavaScript Proxy object.
  // 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 and what enumerator is being set. This can be done by 
  // defining "get" and "set" traps.
  constructor(enumObj) {
    const handler = {
      get(target, name) {
        if (typeof target[name] != 'undefined') {
          return target[name]
        }
        throw new Error(`No such enumerator: ${name}`)
      },
      set() {
        throw new Error('Cannot add/update properties on an Enum instance after it is defined')
      }
    }


    // Freeze the target object to prevent modifications
    return new Proxy(enumObj, handler)
  }
}


// Now that we have a generic way of creating Enums, lets create our first Enum!
const httpMethods = new Enum({
  DELETE: "DELETE",
  GET: "GET",
  OPTIONS: "OPTIONS",
  PATCH: "PATCH",
  POST: "POST",
  PUT: "PUT"
})

// Sanity checks
console.log(httpMethods.DELETE)
// logs "DELETE"

try {
  httpMethods.delete = "delete"
} catch (e) {
console.log("Error: ", e.message)
}
// throws "Cannot add/update properties on an Enum instance after it is defined"

try {
  console.log(httpMethods.delete)
} catch (e) {
  console.log("Error: ", e.message)
}
// throws "No such enumerator: delete"


ASIDE: क्या बिल्ली एक छद्म है?

मुझे याद है जब मैंने पहली बार हर जगह प्रॉक्सी शब्द देखना शुरू किया था, तो निश्चित रूप से यह लंबे समय तक मेरे लिए मायने नहीं रखता था। यदि आप अभी हैं, तो मुझे लगता है कि प्रॉक्सी को सामान्य बनाने का एक आसान तरीका है कि उन्हें सॉफ़्टवेयर, संस्थानों या यहां तक ​​कि ऐसे लोगों के बारे में सोचना चाहिए जो दो सर्वर, कंपनियों या लोगों के बीच बिचौलियों या बिचौलियों के रूप में कार्य करते हैं।


MyEnum.valueOf ("someStringValue") कुछ कैसे करें? अपेक्षित: यदि इनपुट स्ट्रिंग में एन्यूमरेटर के एक तत्व का मूल्य है, तो आइटम को वापस करना चाहिए। यदि किसी वस्तु में वह स्ट्रिंग मान नहीं है, तो अपवाद छोड़ दें।
sscarduzio

@sscarduzio आप एनम valueOfवर्ग पर उदाहरण विधि के रूप में निर्दिष्ट करके डिफ़ॉल्ट विधि को ओवरराइड कर सकते हैं । हालाँकि, आप इसे इस तरह से कैसे एक्सेस करना चाहते हैं?
गोविंद राय

मेरी ईनम है const logLevelEnum = नई Enum ({INFO: "info", DEBUG: "debug"}) और मैं इनपुट से एक मनमाना स्ट्रिंग "जानकारी" या "डीबग"। इसलिए मुझे currentLogLevel = logLevelEnum.parseOrThrow (settings.get ("log_level")) जैसे कुछ चाहिए
sscarduzio

1
तुम बस क्यों नहीं कर सकते थे logLevelEnum[settings.get("log_level")]? जोड़ना parseOrThrowकेवल इस बात का दोहराव होगा कि प्रॉक्सी ट्रैप आपके लिए पहले से क्या कर रहे हैं।
गोविंद राय

17

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

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]जो घोषणा के आदेश की परवाह किए बिना "बार" लौटाता है।


1
Plus MyEnum ["बार"] काम करता है जो 1 रिटर्न देता है ... <3 टाइपस्क्रिप्ट अब तक ...
डेविड कार्लास

3
और निश्चित रूप से यदि आप वास्तव में टाइपस्क्रिप्ट का उपयोग कर रहे हैं:enum MyEnum { Foo, Bar, Foobar }
संसद

16

में ES7 , आप स्थिर विशेषताओं पर निर्भर एक सुरुचिपूर्ण Enum कर सकते हैं:

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

फिर

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

लाभ (शाब्दिक वस्तु के बजाय कक्षा का उपयोग करने का) एक मूल वर्ग है Enumतो आपके सभी Enums उस वर्ग का विस्तार करेंगे ।

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

4
क्या आप बता सकते हैं कि पैरेंट क्लास होने का एक फायदा क्यों है? मुझे लगता है कि मुझे कुछ याद आ रहा है!
जॉन जी

7
ऐसा मत करो। new ColorEnum()बिल्कुल कोई मतलब नहीं है।
बेर्गी

3
एक
एनम का

एक बार जब यह भाषा मूल रूप से समर्थन नहीं करती है तो समझ में आएगा कि यह सम्मेलन और इस तरह का उपयोग करेगा! मैं सहमत हूँ!
xpto

मुझे लगता है कि (?) ओपी में क्या हो रहा है, यह है: शुद्ध स्थैतिक का लाभ यह है कि यह एक सिंगलटन के रूप में हर जगह उपलब्ध है, और आपको क्लास को तत्काल करने की आवश्यकता नहीं है - ओपी का सुझाव नहीं है कि आप करते हैं! मुझे लगता है कि वह क्या कह रहा है कि सुपर क्लास है Enumमानक है स्थिर उस पर प्रगणक तरह-तरह getValues(), getNames(), iterate(), आदि अगर ऐसी बात है, आप में से प्रत्येक के लिए नई तरह उन्हें reimplement की जरूरत नहीं है enum
इंजीनियर

15

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

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

और आप अपनी दुश्मनी को इस तरह परिभाषित करते हैं:

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 विधियों का उपयोग करता हूं।

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

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

कुछ नुकसान:

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

14

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

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

12
constऑब्जेक्ट के गुणों को अपरिवर्तनीय नहीं बनाता है, इसका मतलब केवल यह है कि चर Modesको किसी और चीज़ के लिए पुन: असाइन नहीं किया जा सकता है। इसे और अधिक पूर्ण बनाने के लिए, Object.freeze()साथ में उपयोग करें const
रवि जांघ

कृपया उपयोग न करें Object.freeze। यह ऑब्जेक्ट को इनलाइन करने से क्लोजर कंपाइलर को रोकता है।
जैक गिफिन

11

यदि आप Backbone का उपयोग कर रहे हैं , तो आप 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()

8

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

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

1
@JackGiffin मैं मानता हूं कि आपका उत्तर अधिक निष्पादक है और यह मेरा अधिक स्मृति ले सकता है, हालांकि आपको यह नहीं समझना चाहिए कि हर कोई सी + + को लागू करने के तरीके को जानना चाहता है। कृपया अन्य उत्तरों और डेवलपर्स का सम्मान करें, जो आपके ऊपर यह पसंद कर सकते हैं।
एक्सल्टर

7

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

  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

6

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

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

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

Daysअब एनम को संदर्भित करता है Days:

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
    }

})();

यह अच्छा लग रहा है, शायद आपको freezeपिछड़े संगतता के लिए विधि के अस्तित्व की जांच करनी चाहिए ? जैसे,if (Object.freeze) { Object.freeze(values); }
FBB

अच्छी बात! करूँगा!
विविन पालीथ

6

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
}

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

आपको यह सुनिश्चित करने की आवश्यकता नहीं है कि आप इस तरह से अलग-अलग एनम मानों के लिए डुप्लिकेट नंबर असाइन नहीं करते हैं। एक नई वस्तु को सभी एन्युम मानों को तुरंत और सौंपा जाता है।


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

हम्म, बस यह सुनिश्चित करें कि इस कोड को दो बार नहीं मिलता है ...
एंड्रयू

4

टाइपस्क्रिप्ट एनम को लागू करने के लिए यहां कुछ अलग तरीके हैं ।

सबसे आसान तरीका यह है कि किसी ऑब्जेक्ट पर सिर्फ इटरेट किया जाए, ऑब्जेक्ट में इन्वर्टेड की-वैल्यू पेयर को जोड़ा जाए। एकमात्र दोष यह है कि आपको प्रत्येक सदस्य के लिए मान स्वयं सेट करना होगा।

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


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

function enum() {
    var key, val = -1, list = {};
    _.reduce(_.toArray(arguments), function(result, kvp) {    
        kvp = kvp.split("=");
        key = _.trim(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

बहुत चालाक, धन्यवाद
इलान

4

मैंने अभी-अभी एनपीएम पैकेज gen_enum प्रकाशित किया है जिससे आप जावास्क्रिप्ट में 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 पर चेकआउट करें

अपडेट

मैं gen_enumपैकेज को अप्रचलित करता हूं और फ़ंक्शन को कॉन्स्टेज पैकेज में विलय कर देता हूं , जो अपरिवर्तनीय वस्तुओं, JSON स्ट्रिंग डिसेरिएलाइज़ेशन, स्ट्रिंग कॉन्स्टेंट और बिटमैप पीढ़ी आदि सहित अधिक सुविधाएँ प्रदान करता है। चेकआउट https://www.npmjs.com/package/constjs अधिक जानकारी के लिए।

अपग्रेड gen_enumकरने के लिए constjsसिर्फ स्टेटमेंट बदलने के लिए

var genEnum = require('gen_enum');

सेवा

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

4

सबसे सरल समाधान:

सृजन करना

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

मान प्राप्त करें

console.log(Status.Ready) // 1

चाबी देना

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

4

मैंने एक Enum क्लास बनाई है जो O (1) में मान और नाम ला सकती है। यह सभी Names और Values ​​युक्त Object Array भी उत्पन्न कर सकता है।

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 += "<option value='" + this[k] + "'>" + k + "</option>";
            }
            this._reserved._selectOptionsHTML = html;
        }
        return this._reserved._selectOptionsHTML;
    };
}).call(Enum.prototype);

आप इसे इस तरह कर सकते हैं:

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

एक मान लाने के लिए (जैसे सी # में एनम):

var val2 = enum1.item2;

मूल्य के लिए एक नाम लाने के लिए (विभिन्न नामों के लिए समान मूल्य डालते समय अस्पष्ट हो सकता है):

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

किसी ऑब्जेक्ट में प्रत्येक नाम और मान के साथ एक सरणी प्राप्त करने के लिए:

var arr = enum1.GetObjArr();

उत्पन्न करेगा:

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

आप आसानी से HTML चुनिंदा विकल्प भी प्राप्त कर सकते हैं:

var html = enum1.GetSelectOptionsHTML();

जो धारण करता है:

"<option value='0'>item1</option>..."

4

भले ही ES2015 में केवल स्थिर विधियाँ (और स्थैतिक गुण नहीं) समर्थित हैं ( यहाँ भी देखें , .215.2.2.2.2), उत्सुकता से आप नीचे दिए गए बबेल के साथ es2015प्रीसेट का उपयोग कर सकते हैं :

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

मैंने पाया कि यह मॉड्यूल के अनुसार भी काम कर रहा है (उदाहरण के लिए CellStateकिसी अन्य मॉड्यूल से एनम का आयात करना ) और जब मैं वेबपैक का उपयोग करके किसी मॉड्यूल का आयात करता हूं।

इस पद्धति का अधिकांश अन्य उत्तरों पर लाभ यह है कि आप इसे स्थिर प्रकार के चेकर (जैसे फ्लो ) के साथ उपयोग कर सकते हैं और आप स्थैतिक प्रकार की जाँच का उपयोग करते हुए विकास के समय में यह दावा कर सकते हैं, कि आपके चर, पैरामीटर आदि विशिष्ट हैं। CellState" enum "बजाय कुछ अन्य enum (जो कि अगर आपने जेनेरिक ऑब्जेक्ट्स या सिंबल का उपयोग किया है तो अंतर करना असंभव होगा)।

अपडेट करें

उपरोक्त कोड में एक कमी है कि यह एक प्रकार की अतिरिक्त वस्तुओं को बनाने की अनुमति देता है CellState(भले ही कोई उन्हें CellStateजमे हुए क्षेत्रों के स्थिर क्षेत्रों में असाइन नहीं कर सकता है )। फिर भी, नीचे अधिक परिष्कृत कोड निम्नलिखित लाभ प्रदान करता है:

  1. अधिक प्रकार की कोई वस्तु नहीं CellStateबनाई जा सकती है
  2. आपको इस बात की गारंटी दी जाती है कि किसी भी दो एनुम इंस्टेंसेस को एक ही कोड नहीं दिया गया है
  3. उपयोगिता एक स्ट्रिंग प्रतिनिधित्व से वापस पाने के लिए विधि
  4. valuesसमारोह है कि रिटर्न enum के सभी उदाहरणों से ऊपर, मैनुअल (और त्रुटि प्रवण) रास्ते में वापसी मान बनाने के लिए नहीं है।

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

अच्छा उदाहरण :-)
अशरफ.शाक

4

es7 रास्ता, (पुनरावृत्ति, फ्रीज), उपयोग:

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'

कोड:

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(', ') }

}

4

यह कैसे टाइपस्क्रिप्ट इसका enumजावास्क्रिप्ट में अनुवाद करता है:

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

अभी:

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

पहले मैं उलझन में था कि obj[1]रिटर्न क्यों दिया गया है 'Active', लेकिन फिर एहसास हुआ कि इसका मृत सरल - असाइनमेंट ऑपरेटर मूल्य प्रदान करता है और फिर इसे लौटा देता है:

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

4

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

    var Enum = (function(foo) {

    var EnumItem = function(item){
        if(typeof item == "string"){
            this.name = item;
        } else {
            this.name = item.name;
        }
    }
    EnumItem.prototype = new String("DEFAULT");
    EnumItem.prototype.toString = function(){
        return this.name;
    }
    EnumItem.prototype.equals = function(item){
        if(typeof item == "string"){
            return this.name == item;
        } else {
            return this == item && this.name == item.name;
        }
    }

    function Enum() {
        this.add.apply(this, arguments);
        Object.freeze(this);
    }
    Enum.prototype.add = function() {
        for (var i in arguments) {
            var enumItem = new EnumItem(arguments[i]);
            this[enumItem.name] = enumItem;
        }
    };
    Enum.prototype.toList = function() {
        return Object.keys(this);
    };
    foo.Enum = Enum;
    return Enum;
})(this);
var STATUS = new Enum("CLOSED","PENDING", { name : "CONFIRMED", ackd : true });
var STATE = new Enum("CLOSED","PENDING","CONFIRMED",{ name : "STARTED"},{ name : "PROCESSING"});

जैसा कि इस पुस्तकालय में परिभाषित किया गया है। https://github.com/webmodule/foo/blob/master/foo.js#L217

पूरा उदाहरण https://gist.github.com/lnt/bb13a2fd63cdb8bce85fd62965a20026


3

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

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

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

6
फ़ंक्शन अनावश्यक है और आपको वही परिणाम देता है जो ओपी पोस्ट करता है।
सिल्डोरेथ

3

लेखन के रूप में, अक्टूबर 2014 - इसलिए यहां एक समकालीन समाधान है। एक नोड मॉड्यूल के रूप में समाधान लिख रहा है, और इसमें मोचा और चाय का उपयोग करके एक परीक्षण शामिल है, साथ ही अंडरस्कोर जेएस भी शामिल है। आप इन्हें आसानी से अनदेखा कर सकते हैं, और यदि पसंद है तो बस Enum कोड ले सकते हैं।

पीढ़ी-दर-परत पुस्तकालयों आदि के साथ बहुत सारे पोस्ट देखें। जावास्क्रिप्ट में एनम सपोर्ट प्राप्त करने का उपाय इतना सरल है कि वास्तव में इसकी आवश्यकता है। यहाँ कोड है:

फ़ाइल: 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;

और यह बताने के लिए एक परीक्षण कि यह आपको क्या देता है:

फ़ाइल: 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.stringify(fileFormatEnum), 'Unexpected format');
            assert('["CSV","TSV"]' === JSON.stringify(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.stringify(encodingEnum), 'Unexpected format');
            assert('["UTF8","SHIFT_JIS"]' === JSON.stringify(encodingEnum.keys), 'Unexpected keys format');
        });
    });

});

जैसा कि आप देख सकते हैं, आपको एक Enum factory मिलता है, आप बस enum.keys पर कॉल करके सभी कुंजियाँ प्राप्त कर सकते हैं, और आप स्वयं कुंजियों को पूर्णांक स्थिरांक से मिला सकते हैं। और आप विभिन्न मूल्यों के साथ कारखाने का पुन: उपयोग कर सकते हैं, और नोड के मॉड्यूलर दृष्टिकोण का उपयोग करके उन उत्पन्न एनम को निर्यात कर सकते हैं।

एक बार फिर, अगर आप सिर्फ एक आकस्मिक उपयोगकर्ता हैं, या ब्राउज़र आदि में, बस कोड का कारखाना हिस्सा लेते हैं, तो संभवतः अंडरस्कोर लाइब्रेरी को हटा दें, यदि आप इसे अपने कोड में उपयोग नहीं करना चाहते हैं।


5
क्या आप केवल "यहां एक आकस्मिक उपयोगकर्ता के रूप में ऐसा करने के लिए एक उत्तर पोस्ट कर सकते हैं जो सिर्फ एनम चाहते हैं, न कि कारखानों, अंडरस्कोर, या कुछ भी फैंसी"?
ग्रीनएजजादे

5
भले ही यह डेवलपर्स की नज़र से बहुत बढ़िया है, यह बहुत साफ या पठनीय नहीं है। ओपी से एनुम समाधान हर तरह से आसान और अधिक पठनीय है, और इसलिए उपयोग करने के लिए बेहतर है। फिर भी, बहुत सुखद है कि आप इस के साथ आए।
डेविड

3

यह उपयोग करना आसान है, मुझे लगता है। https://stackoverflow.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);

अपडेट करें:

मेरा सहायक कोड है ( TypeHelper)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.