क्या जावास्क्रिप्ट गारंटी ऑब्जेक्ट प्रॉपर्टी ऑर्डर करता है?


647

अगर मैं इस तरह से एक ऑब्जेक्ट बनाता हूं:

var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";

क्या परिणामी वस्तु हमेशा इस तरह दिखेगी?

{ prop1 : "Foo", prop2 : "Bar" }

यही है, क्या गुण उसी क्रम में होंगे जो मैंने उन्हें जोड़ा था?





1
@TJCrowder क्या आप इस पर थोड़ा और विस्तार कर सकते हैं कि स्वीकृत उत्तर अब सटीक क्यों नहीं है? आपके द्वारा जोड़ा गया प्रश्न इस विचार को उबाल देता है कि संपत्ति के आदेश की प्रति अभी भी गारंटी नहीं है।
1929 में शून्य 298

2
@ zero298: उस प्रश्न का स्वीकृत उत्तर स्पष्ट रूप से ES2015 + के रूप में निर्दिष्ट संपत्ति क्रम का वर्णन करता है । विरासत परिचालन ( for-in, Object.keys) यह समर्थन करने के लिए (आधिकारिक तौर पर) की जरूरत नहीं है, लेकिन वहाँ है ऑर्डर करें। (अनौपचारिक रूप से: फ़ायरफ़ॉक्स, क्रोम, और एज सभी के लिए निर्दिष्ट क्रम का पालन करते हैं यहां तक ​​कि ऑब्जेक्ट-इन और ऑब्जेक्ट्स के लिए, जहाँ उन्हें आधिकारिक रूप से आवश्यक नहीं है: jsfiddle.net/arhbn3k2/1 )
TJ Crowder

जवाबों:


474

ऑब्जेक्ट के लिए पुनरावृति क्रम ES2015 के बाद से नियमों के एक निश्चित सेट का पालन करता है , लेकिन यह (हमेशा) सम्मिलन आदेश का पालन नहीं करता है । सीधे शब्दों में कहें तो पुनरावृति क्रम स्ट्रिंग्स कुंजियों के लिए सम्मिलन आदेश का एक संयोजन है, और नंबर जैसी कुंजियों के लिए आरोही क्रम है:

// key order: 1, foo, bar
const obj = { "foo": "foo", "1": "1", "bar": "bar" }

किसी सरणी या Mapऑब्जेक्ट का उपयोग करना इसे प्राप्त करने का एक बेहतर तरीका हो सकता है। Mapशेयरों के साथ कुछ समानताएं Objectऔर कुंजी प्रविष्टि के क्रम में दोहराया जा करने के लिए की गारंटी देता है , बिना किसी अपवाद के:

मानचित्र में कुंजियों का आदेश दिया जाता है, जबकि ऑब्जेक्ट में जोड़े गए कुंजी नहीं होते हैं। इस प्रकार, जब इस पर पुनरावृत्ति होती है, तो एक मैप ऑब्जेक्ट प्रविष्टि के क्रम में चाबियाँ देता है। (ध्यान दें कि ECMAScript 2015 में कल्पना की गई वस्तुएं स्ट्रिंग और सिंबल कीज के लिए क्रिएशन ऑर्डर को संरक्षित करती हैं, इसलिए किसी ऑब्जेक्ट के ट्रैवर्सल यानी केवल स्ट्रिंग कीज़ को इंसर्शन के क्रम में चाबियाँ मिलेंगी)

ध्यान दें, ES2015 से पहले वस्तुओं में गुण आदेश की गारंटी नहीं थी। ECMAScript तीसरे संस्करण (पीडीएफ) से एक वस्तु की परिभाषा :

4.3.3 वस्तु

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


पूर्णांक कुंजियों का व्यवहार सभी ब्राउज़रों के अनुरूप नहीं है। कुछ पुराने ब्राउज़रों ने प्रविष्टि क्रम में (स्ट्रिंग कुंजियों के साथ) पूर्णांक कुंजी को पुनरावृत्त किया और कुछ को आरोही क्रम में।
डेव डॉपसन

1
@DaveDopson - सही-अप्रचलित ब्राउज़र वर्तमान विनिर्देश का पालन नहीं करते हैं, क्योंकि वे अद्यतन नहीं हैं।
टीजे क्राउडर

199

हाँ (गैर-पूर्णांक कुंजियों के लिए)।

अधिकांश ब्राउज़रों के रूप में वस्तु गुण पुनरावृति:

  1. आरोही क्रम में पूर्णांक कुंजियाँ (और "1" जैसे स्ट्रिंग्स जो कि पार्स के रूप में पार्स होती हैं)
  2. प्रविष्टि क्रम में स्ट्रिंग कुंजी, (ES2015 इसकी गारंटी देता है और सभी ब्राउज़र अनुपालन करते हैं)
  3. प्रविष्टि क्रम में प्रतीक नाम (ES2015 इसकी गारंटी देता है और सभी ब्राउज़र अनुपालन करते हैं)

कुछ पुराने ब्राउज़र श्रेणी # 1 और # 2 को जोड़ते हैं, प्रविष्टि क्रम में सभी कुंजियों को पुनरावृत्त करते हैं। यदि आपकी चाबियाँ पूर्णांक के रूप में पार्स कर सकती हैं, तो किसी भी विशिष्ट पुनरावृत्ति क्रम पर भरोसा नहीं करना सबसे अच्छा है।

वर्तमान भाषा युक्ति (ES2015 के बाद से) प्रविष्टि क्रम संरक्षित है, पूर्णांक के रूप में पार्स करने वाली कुंजियों (जैसे "7" या "99") को छोड़कर, जहां व्यवहार ब्राउज़रों के बीच भिन्न होता है। उदाहरण के लिए, जब कुंजियाँ संख्यात्मक के रूप में पार्स होती हैं, तो क्रोम / वी 8 सम्मिलन आदेश का सम्मान नहीं करता है।

ओल्ड लैंग्वेज स्पेस (ES2015 से पहले) : Iteration ऑर्डर तकनीकी रूप से अपरिभाषित था, लेकिन सभी प्रमुख ब्राउज़रों ने ES2015 व्यवहार का अनुपालन किया।

ध्यान दें कि ES2015 व्यवहार मौजूदा व्यवहार द्वारा संचालित भाषा कल्पना का एक अच्छा उदाहरण था, न कि दूसरे तरीके से। उस बैक-संगतता संगतता की गहरी समझ पाने के लिए, http://code.google.com/p/v8/issues/detail?id=164 , Chrome बग देखें जो Chrome के पुनरावृत्ति क्रम व्यवहार के पीछे डिज़ाइन निर्णयों को विस्तार से शामिल करता है । उस बग रिपोर्ट की टिप्पणियों में से एक (बल्कि रायशुमारी):

मानक हमेशा कार्यान्वयन का पालन करते हैं, यही वह जगह है जहां से एक्सएचआर आया था, और Google गियर्स को लागू करके और फिर एचटीएमएल 5 कार्यक्षमता को गले लगाकर एक ही काम करता है। सही तय यह है कि ईसीएमए औपचारिक रूप से डी-फैक्टो मानक व्यवहार को कल्पना के अगले संशोधन में शामिल करे।


2
@BenjaminGruenbaum - यही मेरी बात थी। 2014 तक सभी प्रमुख विक्रेताओं का एक समान कार्यान्वयन था और इस प्रकार मानकों का पालन अंततः (यानी, 2015 में) होगा।
डेव डॉपसन

2
वैसे: रिएक्ट createFragmentएपीआई पहले से ही इस पर निर्भर करता है ... ik
mik01aj

7
@BenjaminGruenbaum आपकी टिप्पणी झूठी है। ES2015 में आदेश केवल चयनित विधियों के लिए गारंटी है । देखें जवाब की ftor नीचे।
पायोटर डोब्रोगोस्ट

82

सामान्य वस्तुओं में संपत्ति का आदेश जावास्क्रिप्ट में एक जटिल विषय है।

जबकि ES5 में स्पष्ट रूप से कोई आदेश निर्दिष्ट नहीं किया गया है, ES2015 में कुछ मामलों में एक आदेश है। निम्नलिखित वस्तु है:

o = Object.create(null, {
  m: {value: function() {}, enumerable: true},
  "2": {value: "2", enumerable: true},
  "b": {value: "b", enumerable: true},
  0: {value: 0, enumerable: true},
  [Symbol()]: {value: "sym", enumerable: true},
  "1": {value: "1", enumerable: true},
  "a": {value: "a", enumerable: true},
});

इसका परिणाम निम्न क्रम में (कुछ मामलों में) है:

Object {
  0: 0,
  1: "1",
  2: "2",
  b: "b",
  a: "a",
  m: function() {},
  Symbol(): "sym"
}
  1. पूर्णांक जैसी कुंजियाँ आरोही क्रम में
  2. प्रविष्टि क्रम में सामान्य कुंजी
  3. सम्मिलन क्रम में प्रतीक

इस प्रकार, तीन खंड हैं, जो प्रविष्टि क्रम को बदल सकते हैं (उदाहरण के रूप में हुआ)। और पूर्णांक की तरह कुंजियाँ प्रविष्टि क्रम पर बिल्कुल नहीं टिकती हैं।

सवाल यह है कि ES2015 की युक्ति में इस आदेश की गारंटी किन तरीकों से दी गई है?

निम्न तरीके दिखाए गए आदेश की गारंटी देते हैं:

  • Object.assign
  • Object.defineProperties
  • Object.getOwnPropertyNames
  • Object.getOwnPropertySymbols
  • Reflect.ownKeys

निम्नलिखित विधियाँ / छोरें बिना किसी आदेश के गारंटी देती हैं:

  • Object.keys
  • अंदर के लिए
  • JSON.parse
  • JSON.stringify

निष्कर्ष: ES2015 में भी आपको जावास्क्रिप्ट में सामान्य वस्तुओं के संपत्ति क्रम पर भरोसा नहीं करना चाहिए। यह त्रुटियों के लिए प्रवण है। Mapइसके बजाय उपयोग करें ।


मैंने नोड v8.11 में निष्कर्ष का मोटे तौर पर परीक्षण किया और यह सही है।
मर्लिन.ये

1
@BenjaminGruenbaum कोई विचार?
एवोल्यूशनबॉक्स

Object.entries गारंटी आदेश, पूर्णांक नियम का पालन करते हुए
Mojimi

1
+1 के लिए "यहां तक ​​कि ES2015 में भी आपको जावास्क्रिप्ट में सामान्य वस्तुओं की संपत्ति के आदेश पर भरोसा नहीं करना चाहिए। यह त्रुटियों से ग्रस्त है। इसके बजाय मानचित्र का उपयोग करें।" जब संपत्ति का अनुपालन हो जाता है तो आप संपत्ति के आदेश पर भरोसा नहीं कर सकते। यदि आप पुराने ब्राउज़रों का समर्थन करना चाहते हैं, तो आप इसके लिए बैकवर्ड तुलनीयता के लिए भी कैसे परीक्षण करेंगे?
शून्य 298

1
क्या इसके बारे में कोई आधिकारिक दस्तावेज या संदर्भ है?
मारो

66

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

ECMAScript विनिर्देश कहा करते थे:

गुणों की गणना करने वाले यांत्रिकी और आदेश ... निर्दिष्ट नहीं है।

हालांकि ES2015 और बाद में गैर-पूर्णांक कुंजियों को प्रविष्टि क्रम में वापस कर दिया जाएगा।


16
क्रोम अन्य ब्राउज़रों के लिए एक अलग क्रम लागू करता है। कोड देखें। http://www.p/v8/issues/detail
टिम डाउन

9
ओपेरा 10.50 और इसके बाद के संस्करण, साथ ही IE9, क्रोम के आदेश से मेल खाते हैं। फ़ायरफ़ॉक्स और सफारी अब एक अल्पसंख्यक हैं (और वे दोनों भी ऑब्जेक्ट / एरेज़ के लिए अलग-अलग ऑर्डर का उपयोग करते हैं)।
gsnedders

1
@ कहीं भी स्पष्ट रूप से आदेश की कोई गारंटी नहीं है, इसलिए हमेशा यह मान लेना चाहिए कि आदेश प्रभावी रूप से यादृच्छिक है।
Alnitak

1
@Veverke नहीं, आदेश कुछ भी वैसा नहीं है जैसा कि अनुमान है। यह किसी भी समय बदलने के लिए निर्भर और विषय पर लागू होता है, और हर बार जब आपका ब्राउज़र खुद को अपडेट करता है (उदाहरण के लिए) बदल सकता है।
अलनीतक

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

42

यह पूरा जवाब कल्पना के अनुपालन के संदर्भ में है, न कि किसी भी इंजन को किसी विशेष क्षण में या ऐतिहासिक रूप से।

आम तौर पर, नहीं

वास्तविक प्रश्न बहुत अस्पष्ट है।

क्या गुण उसी क्रम में होंगे जो मैंने उन्हें जोड़ा था

किस संदर्भ में?

उत्तर है: यह कई कारकों पर निर्भर करता है। सामान्य तौर पर, नहीं

कभी कभी हाँ

यहाँ आप सादे के लिए संपत्ति के प्रमुख आदेश पर भरोसा कर सकते हैं Objects:

  • ES2015 अनुरूप इंजन
  • खुद के गुण
  • Object.getOwnPropertyNames(), Reflect.ownKeys(),Object.getOwnPropertySymbols(O)

सभी मामलों में इन विधियों में गैर-गणना करने योग्य संपत्ति कुंजियाँ और ऑर्डर कुंजियाँ शामिल हैं जो कि [[OwnPropertyKeys]]नीचे (नीचे देखें) द्वारा निर्दिष्ट हैं। वे उन प्रमुख मूल्यों के प्रकार में भिन्न होते हैं जिनमें वे शामिल होते हैं ( Stringऔर / या Symbol)। इस संदर्भ Stringमें पूर्णांक मान शामिल हैं।

Object.getOwnPropertyNames(O)

रिटर्न Oके स्वयं के Stringगुण ( संपत्ति के नाम )।

Reflect.ownKeys(O)

रिटर्न Oखुद के Stringऔर Symbolगुणित गुण है।

Object.getOwnPropertySymbols(O)

रिटर्न Oके अपने खुद के Symbolगुण है।

[[OwnPropertyKeys]]

आदेश अनिवार्य रूप से है: पूर्णांक-जैसा Stringsआरोही क्रम में, गैर-पूर्णांक-जैसा Stringsसृजन क्रम, सृजन क्रम में प्रतीक। किस फ़ंक्शन के आधार पर यह लागू होता है, इनमें से कुछ प्रकार शामिल नहीं हो सकते हैं।

विशिष्ट भाषा यह है कि कुंजियाँ निम्नलिखित क्रम में लौटाई जाती हैं:

  1. ... प्रत्येक वस्तु Pकी कुंजी O[वस्तु को पुनरावृत्त किया जा रहा है] जो कि पूर्णांक सूचकांक है, आरोही संख्यात्मक सूचकांक क्रम में

  2. ... प्रत्येक अपनी संपत्ति कुंजी Pकी Oहै कि एक स्ट्रिंग है, लेकिन नहीं एक पूर्णांक सूचकांक, संपत्ति सृजन क्रम में है

  3. ... प्रत्येक अपनी संपत्ति कुंजी Pकी Oहै कि एक प्रतीक, संपत्ति सृजन क्रम में है

Map

यदि आप ऑर्डर किए गए नक्शे में रुचि रखते हैं, तो आपको Mapसादे के बजाय ES2015 में पेश किए गए प्रकार का उपयोग करने पर विचार करना चाहिए Objects


13

आधुनिक ब्राउज़रों में आप Mapऑब्जेक्ट के बजाय डेटा संरचना का उपयोग कर सकते हैं ।

डेवलपर मोज़िला> नक्शा

एक मानचित्र वस्तु सम्मिलन क्रम में अपने तत्वों को पुनरावृत्त कर सकती है ...


7

ES2015 में, यह करता है, लेकिन ऐसा नहीं है जो आप सोच सकते हैं

ES2015 तक किसी ऑब्जेक्ट में कुंजियों के क्रम की गारंटी नहीं दी गई थी। यह कार्यान्वयन-परिभाषित था।

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

ऑर्डर को परिभाषित किया गया है, अमूर्त ऑपरेशन के तहत ऑर्डिनरीऑनप्रोपरेटीके , जो किसी वस्तु की अपनी कुंजियों पर चलने के सभी तरीकों को रेखांकित करता है। Paraphrased, आदेश इस प्रकार है:

  1. सभी पूर्णांक अनुक्रमणिका कुंजियाँ (सामान "1123", जैसे "55", आदि) आरोही संख्यात्मक क्रम में हैं।

  2. सृजन के क्रम में सभी स्ट्रिंग कुंजी जो पूर्णांक सूचक नहीं हैं, सबसे पुराना है।

  3. सृजन के क्रम में सभी प्रतीक कुंजियाँ (सबसे पुरानी-पहली)।

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

कुछ अपवादों में विरासत में मिली चाबियों की गणना करने के तरीके शामिल हैं, जैसे कि for .. inलूप। for .. inपाश विवरणों के आधार पर आदेश की गारंटी नहीं है।


7

ES2015 के अनुसार, संपत्ति के गुणों पर पुनरावृति करने वाले कुछ तरीकों के लिए संपत्ति के आदेश की गारंटी है। लेकिन दूसरों को नहीं । दुर्भाग्य से, जिन तरीकों से ऑर्डर करने की गारंटी नहीं होती है, वे आमतौर पर सबसे अधिक उपयोग किए जाते हैं:

  • Object.keys, Object.values,Object.entries
  • for..in छोरों
  • JSON.stringify

लेकिन, ES2020 के रूप में, इन पहले कुटिल तरीकों के लिए संपत्ति आदेश होगा विनिर्देश द्वारा गारंटी दी जा , दूसरों के रूप में एक ही नियतात्मक तरीके से अधिक दोहराया जा करने के लिए करने के लिए की वजह से समाप्त : प्रस्ताव यांत्रिकी में लिए-

उन तरीकों के साथ जैसे कि एक गारंटीकृत पुनरावृत्ति क्रम (जैसे Reflect.ownKeysऔर Object.getOwnPropertyNames), पहले से अनिर्दिष्ट तरीके भी निम्न क्रम में पुनरावृति करेंगे:

  • न्यूमेरिक ऐरे कीज, आरोही अंकीय क्रम में
  • प्रविष्टि क्रम में अन्य सभी गैर-प्रतीक कुंजियाँ
  • सम्मिलन क्रम में प्रतीक कुंजियाँ

यह वही है जो हर कार्यान्वयन पहले से ही करता है (और कई वर्षों तक किया है), लेकिन नए प्रस्ताव ने इसे आधिकारिक बना दिया है।

हालाँकि, वर्तमान विनिर्देशन के लिए। It पुनरावृत्ति क्रम से निकलता है " लगभग पूरी तरह से अनिर्दिष्ट , वास्तविक इंजन अधिक सुसंगत होते हैं:"

ECMA-262 में विशिष्टता की कमी वास्तविकता को प्रतिबिंबित नहीं करती है। पिछले वर्षों में चर्चा में, कार्यान्वयनकर्ताओं ने देखा है कि फॉर-इन के व्यवहार पर कुछ अड़चनें हैं, जो कोई भी व्यक्ति जो वेब पर कोड चलाना चाहता है, का पालन करने की आवश्यकता है।

क्योंकि प्रत्येक कार्यान्वयन पहले से ही गुणों से अधिक अनुमान लगाता है, इसे पीछे की संगतता को तोड़े बिना विनिर्देश में डाला जा सकता है।


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

न तो वस्तु को पुनरावृत्त किया जा रहा है और न ही इसकी प्रोटोटाइप श्रृंखला में कुछ भी एक छद्म, टाइप की गई सरणी, मॉड्यूल नेमस्पेस ऑब्जेक्ट, या बाहरी विदेशी वस्तु है।

इसके प्रोटोटाइप श्रृंखला में न तो वस्तु और न ही कुछ भी इसके प्रोटोटाइप परिवर्तन के दौरान है।

न तो वस्तु और न ही इसकी प्रोटोटाइप श्रृंखला में कुछ भी संपत्ति के दौरान हटाई गई है।

ऑब्जेक्ट की प्रोटोटाइप श्रृंखला में कुछ भी नहीं है संपत्ति में पुनरावृत्ति के दौरान जोड़ा गया है।

ऑब्जेक्ट की कोई भी प्रॉपर्टी या उसके प्रोटोटाइप चेन में किसी भी चीज की इटेरिएबिलिटी चेंज नहीं होती है।

कोई भी गैर-विलुप्त होने वाली प्रॉपर्टी की परिकल्पना नहीं होती।


5

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

var myarr = [{somfield1: 'x', somefield2: 'y'},
{somfield1: 'a', somefield2: 'b'},
{somfield1: 'i', somefield2: 'j'}];

इस तरह आप लूप के लिए एक नियमित रूप से उपयोग कर सकते हैं और सम्मिलित आदेश दे सकते हैं। यदि आवश्यक हो तो आप एक नए सरणी में इसे सॉर्ट करने के लिए ऐरे सॉर्ट विधि का उपयोग कर सकते हैं।


3

बस यह मुश्किल रास्ता मिल गया।

Redux के साथ रिएक्ट का उपयोग करते हुए, बच्चों को उत्पन्न करने के लिए मैं जिस कंटेनर की चाबी लेना चाहता हूं, उसे स्टोर में बदले जाने के बाद हर बार रिफ्रेश किया जाता है (Redux की अपरिवर्तनीय अवधारणाओं के अनुसार)।

इस प्रकार, Object.keys(valueFromStore)मुझे लेने के लिए Object.keys(valueFromStore).sort(), ताकि मैं कम से कम अब चाबियों के लिए एक वर्णमाला क्रम रखूं।


-7

से JSON मानक :

एक वस्तु शून्य या अधिक नाम / मूल्य जोड़े का एक अनियंत्रित संग्रह है, जहां एक नाम एक स्ट्रिंग है और एक मूल्य एक स्ट्रिंग, संख्या, बूलियन, अशक्त, वस्तु या सरणी है।

(जोर मेरा)।

तो, नहीं, आप आदेश की गारंटी नहीं दे सकते।


7
यह ECMAScript मानक द्वारा निर्दिष्ट किया गया है - JSON युक्ति नहीं।
एल्निटैक

7
@Alnitak, @Iacqui: JSON केवल ECMAScript विनिर्देशन से इसे लेता है। यह JSON के लिए भी निर्दिष्ट है, लेकिन यह वास्तव में प्रश्न से संबंधित नहीं है।
पाओलो एबरमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.