एक "के लिए (में ...)" लूप में तत्व आदेश


205

क्या जावास्क्रिप्ट / लूप में "जावास्क्रिप्ट" पाश हैशटैब / तत्वों के माध्यम से उस क्रम में होता है, जिस क्रम में वे घोषित किए जाते हैं? क्या कोई ब्राउज़र है जो इसे क्रम में नहीं करता है?
मैं जिस वस्तु का उपयोग करना चाहता हूं उसे एक बार घोषित किया जाएगा और कभी भी संशोधित नहीं किया जाएगा।

मान लीजिए कि मेरे पास है:

var myObject = { A: "Hello", B: "World" };

और मैं उन्हें आगे उपयोग करता हूं:

for (var item in myObject) alert(item + " : " + myObject[item]);

क्या मैं सबसे सभ्य ब्राउज़रों में 'बी: "वर्ल्ड" से पहले हमेशा "ए:" हैलो "की उम्मीद कर सकता हूं?


61
वे केवल संभावित ब्राउज़रों और वेरिएंट के सबसेट का परीक्षण कर रहे हैं। भविष्य के किसी भी ब्राउज़र का उल्लेख नहीं करना। यह मानना ​​गलत है कि गैर-असफल परीक्षण किसी भी प्रकार का ठोस प्रमाण प्रदान करता है।
जेम्स ह्यूजेस

6
मुझे संदेह है कि मेरी अपनी सीमित जावास्क्रिप्ट क्षमता एसओ भीड़ से बेहतर होगी। इसके अलावा कौन जानता है कि कौन सा अजीब ब्राउज़र वहाँ से बाहर निकलता है? और आप जवाब में देख सकते हैं कि GChrome में एक बग है जो मेरे सरल उदाहरण के मामले में स्पष्ट नहीं होगा।
चक्र


जवाबों:


214

जॉन रिजिग का उद्धरण :

वर्तमान में सभी प्रमुख ब्राउज़र किसी ऑब्जेक्ट के गुणों पर उस क्रम में लूप करते हैं जिसमें वे परिभाषित किए गए थे। कुछ मामलों को छोड़कर क्रोम ऐसा ही करता है। [...] इस व्यवहार को स्पष्ट रूप से ECMAScript विनिर्देश द्वारा अपरिभाषित छोड़ दिया गया है। ECMA-262 में, धारा 12.6.4:

गुणों की गणना करने वाले यांत्रिकी ... कार्यान्वयन निर्भर है।

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

सभी ब्राउज़र क्रोम और ओपेरा के अपवाद के साथ परिभाषा के आदेश का सम्मान करते हैं जो प्रत्येक गैर-संख्यात्मक संपत्ति के नाम के लिए करते हैं। इन दो ब्राउज़रों में संपत्तियों को पहले गैर-संख्यात्मक संपत्ति के आगे खींचा जाता है (इसका अर्थ है कि वे सरणियों को कैसे लागू करते हैं)। आदेश भी उसी के लिए है Object.keys

इस उदाहरण से यह स्पष्ट होना चाहिए कि क्या होता है:

var obj = {
  "first":"first",
  "2":"2",
  "34":"34",
  "1":"1",
  "second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"

इस की तकनीकी इस तथ्य से कम महत्वपूर्ण नहीं है कि यह किसी भी समय बदल सकता है। इस तरह रहने वाली चीजों पर भरोसा न करें।

संक्षेप में: यदि आपके लिए आदेश महत्वपूर्ण है, तो एक सरणी का उपयोग करें।


3
ज़रुरी नहीं। Chrome अन्य ब्राउज़रों के समान आदेश लागू नहीं करता है: code.google.com/p/v8/issues/detail?id=164
टिम डाउन

19
"एक सरणी का उपयोग करें यदि ऑर्डर आपके लिए महत्वपूर्ण है": जब आप JSON का उपयोग कर रहे हों तो क्या होगा?
HM2K

11
@ HM2K, एक ही बात, कल्पना कहती है "एक वस्तु शून्य या अधिक नाम / मूल्य जोड़े का एक अनियंत्रित संग्रह है।" JSON जावास्क्रिप्ट नहीं है: एक सर्वर को आपके हाथ लगाने के आदेश का सम्मान नहीं करना चाहिए (और शायद नहीं होगा)।
बोरगोर

7
फ़ायरफ़ॉक्स क्योंकि इसके 21 संस्करण अब प्रविष्टि आदेश का सम्मान नहीं करते हैं।
डॉक्टर दावलुज़

2
यह उत्तर ES2015 में गलत है।
बेंजामिन ग्रुएनबाम 18

54

एक साल बाद इसे उछाल कर ...

यह 2012 है और प्रमुख ब्राउज़र अभी भी अलग हैं:

function lineate(obj){
    var arr = [], i;
    for (i in obj) arr.push([i,obj[i]].join(':'));
    console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */  lineate(obj);
obj.a = 4;
/* log2 */  lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */  lineate(obj);

वर्तमान ब्राउज़र में जिस्ट या टेस्ट

सफारी 5, फ़ायरफ़ॉक्स 14

["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]

क्रोम 21, ओपेरा 12, नोड 0.6, फ़ायरफ़ॉक्स 27

["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]

IE9

[123:xyz,a:1,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 

16
यहाँ क्या समस्या है? बिल्कुल जैसा कि विनिर्देश कहता है, यह कुंजी / वैल जोड़े की एक अनियंत्रित सूची है।
nickf

5
nickf: कार्यान्वयन सही हैं कि वे वही करते हैं जो कल्पना कहती है। मुझे लगता है कि हर कोई इस बात से सहमत है कि जावास्क्रिप्ट युक्ति है .. ठीक है, मैं "गलत" शब्द का उपयोग नहीं करना चाहता, "बेहद बेवकूफ और कष्टप्रद" कैसे? : P
बॉक्सिंग

10
@ बॉक्सिंग: हैश मैप (टेबल / जो भी हो) के रूप में ऑब्जेक्ट के बारे में सोचें। अधिकांश भाषाओं (जावा, पायथन, आदि) में इन प्रकार की डेटा संरचनाएँ क्रमबद्ध नहीं हैं। इसलिए यह आश्चर्यजनक नहीं है कि जावास्क्रिप्ट में भी यही मामला है और यह निश्चित रूप से विनिर्देश को गलत या बेवकूफ नहीं बनाता है।
फेलिक्स क्लिंग

9
मैं ईमानदारी से इस उत्तर (खेद) की बात नहीं देखता। जिस क्रम में संपत्तियों की अधिकता होती है, वह कार्यान्वयन विवरण होता है, और ब्राउज़र विभिन्न जावास्क्रिप्ट इंजनों का उपयोग करते हैं, इसलिए यह अपेक्षा की जाती है कि यह क्रम अलग-अलग हो। यह नहीं बदलेगा।
फेलिक्स क्लिंग

2
एक कला कार्यान्वयन की स्थिति में आप एक वास्तविक सरणी द्वारा समर्थित होने के कारण संख्यात्मक मान क्रम में पूर्णांक गुण प्राप्त करेंगे, और नामांकित गुण छिपे हुए वर्गों / आकृतियों के निर्माण के कारण सम्मिलन क्रम में प्राप्त होंगे। यह अलग-अलग हो सकता है कि क्या वे पूर्णांक गुणों को पहले या नामित गुणों को सूचीबद्ध करते हैं। इसके अलावा deleteदिलचस्प है क्योंकि कम से कम V8 में, यह तुरंत हैश तालिका द्वारा ऑब्जेक्ट का बैकअप लेने का कारण बनता है। हालाँकि, प्रविष्टि क्रम में V8 स्टोर में हैश तालिका। यहां सबसे दिलचस्प परिणाम IE है, मुझे आश्चर्य है कि वे किस तरह की कुरूपता को दूर करने के लिए करते हैं ...
एसेलीजा

27

से ECMAScript भाषा विशिष्टता , खंड 12.6.4 (पर for .. inपाश):

गुणों की गणना करने वाले यांत्रिकी कार्यान्वयन पर निर्भर है। गणना का क्रम वस्तु द्वारा परिभाषित किया गया है।

और खंड 4.3.3 ("ऑब्जेक्ट" की परिभाषा):

यह गुणों का एक अनियंत्रित संग्रह है, जिनमें से प्रत्येक में एक आदिम मूल्य, ऑब्जेक्ट या फ़ंक्शन होता है। किसी वस्तु की संपत्ति में संग्रहीत कार्य को विधि कहा जाता है।

मुझे लगता है कि इसका मतलब यह नहीं है कि आप जावास्क्रिप्ट कार्यान्वयन पर एक सुसंगत क्रम में गणना की जा रही संपत्तियों पर भरोसा कर सकते हैं। (यह किसी भी भाषा के कार्यान्वयन-विशिष्ट विवरण पर भरोसा करने के लिए वैसे भी बुरी शैली होगी।)

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


10

एक वस्तु के तत्व जो एन्यूमरेट्स में / के लिए गुण हैं जिनके पास डोनटेन फ्लैग सेट नहीं है। ECMAScript, उर्फ ​​जावास्क्रिप्ट, मानक स्पष्ट रूप से कहता है कि "एक वस्तु गुणों का एक अनियंत्रित संग्रह है" (देखें http://www.mozilla.org/js/language/E262-3.pdf खंड 8.6)।

यह सभी जावास्क्रिप्ट क्रियान्वयन को मानने के क्रम में मानकों के अनुरूप (सुरक्षित) होने वाला नहीं है।


2
यही कारण है कि वह सवाल पूछ रहा है, बस मानने के बजाय: पी
जेमी पाट

4

संपत्तियों को हटाने के संबंध में Iteration ऑर्डर भी भ्रमित है, लेकिन केवल IE के साथ इस मामले में।

var obj = {};
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';

// IE allows the value to be deleted...
delete obj.b;

// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj) {
    alert(obj[p]); // in IE, will be a, bb, then c;
                   // not a, c, then bb as for FF/Chrome/Opera/Safari
}

यदि http://code.google.com/p/v8/issues/detail?id=164 पर चर्चा किसी भी संकेत है , तो पुनरावृत्ति क्रम को ठीक करने की इच्छा को बदलने के लिए डेवलपर्स के बीच काफी लोकप्रिय इच्छा प्रतीत होती है ।


3

IE6 में, आदेश की गारंटी नहीं है।


2

आदेश पर भरोसा नहीं किया जा सकता है। ओपरा और क्रोम दोनों ही असंक्रमित गुणों की सूची वापस करते हैं।

<script type="text/javascript">
var username = {"14719":"A","648":"B","15185":"C"};

for (var i in username) {
  window.alert(i + ' => ' + username[i]);
}
</script>

ऊपर दिया गया कोड Chrome में B, A, C और C में A, B दिखाता है।


1

यह प्रति प्रश्न का उत्तर नहीं देता है, लेकिन मूल समस्या का समाधान प्रस्तुत करता है।

यह मानते हुए कि आप संरक्षित करने के आदेश पर भरोसा नहीं कर सकते हैं, तो गुणों के रूप में कुंजी और मूल्य के साथ वस्तुओं की एक सरणी का उपयोग क्यों नहीं करें?

var myArray = [
    {
        'key'   : 'key1'
        'value' : 0
    },
    {
        'key'   : 'key2',
        'value' : 1
    } // ...
];

अब, यह सुनिश्चित करने के लिए आप पर निर्भर है कि चाबियाँ अद्वितीय हैं (यह मानते हुए कि यह आपके लिए भी महत्वपूर्ण है। साथ ही, प्रत्यक्ष पते में परिवर्तन, और के लिए (... में) अब अनुक्रमितों को 'कुंजी' के रूप में लौटाता है।

> console.log(myArray[0].key);
key1

> for (let index in myArray) {console.log(myArray[index].value);}
0
1
पेन देखें (... में ...) क्रम में संबोधित करने के लिए JDQ (द्वारा @JDQ पर) CodePen

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