मैं यह कोशिश करूँगा। ध्यान दें कि मैं ECMA से संबद्ध नहीं हूं और उनकी निर्णय लेने की प्रक्रिया में कोई दृश्यता नहीं है, इसलिए मैं निश्चित रूप से नहीं कह सकता कि उन्होंने कुछ भी क्यों किया है या नहीं किया है। हालाँकि, मैं अपनी मान्यताओं को बताता हूँ और अपना सर्वश्रेष्ठ शॉट लेता हूँ।
1. for...of
पहली जगह में एक निर्माण क्यों जोड़ें ?
जावास्क्रिप्ट में पहले से ही एक for...in
निर्माण शामिल है जिसका उपयोग किसी वस्तु के गुणों को पुनरावृत्त करने के लिए किया जा सकता है। हालाँकि, यह वास्तव में एक फॉरेप लूप नहीं है , क्योंकि यह किसी वस्तु पर सभी गुणों को दर्शाता है और केवल साधारण मामलों में ही अनुमानित रूप से काम करता है।
यह अधिक जटिल मामलों में टूट जाता है (सरणियों के साथ, जहां इसका उपयोग या तो हतोत्साहित करता है याfor...in
किसी सरणी के साथ सही तरीके से उपयोग करने के लिए आवश्यक सुरक्षा उपायों द्वारा पूरी तरह से बाधित होता है )। आप hasOwnProperty
(अन्य बातों के अलावा) का उपयोग करके चारों ओर काम कर सकते हैं , लेकिन यह थोड़ा क्लिंक और अशुभ है।
इसलिए इसलिए मेरी धारणा यह है कि for...of
निर्माण से जुड़ी कमियों को दूर करने के लिए निर्माण को जोड़ा जा रहा है for...in
, और चीजों को पुनरावृत्त करते समय अधिक उपयोगिता और लचीलापन प्रदान करता है। लोग for...in
एक forEach
लूप के रूप में व्यवहार करते हैं जो आम तौर पर किसी भी संग्रह पर लागू किया जा सकता है और किसी भी संभावित संदर्भ में समझदार परिणाम उत्पन्न कर सकता है, लेकिन ऐसा नहीं होता है। for...of
पाश फिक्स है।
मैं यह भी मानता हूं कि मौजूदा ES5 कोड के लिए ES6 के तहत चलना और उसी परिणाम का उत्पादन करना महत्वपूर्ण है जैसा कि ES5 के तहत किया गया था, इसलिए for...in
निर्माण के व्यवहार के लिए ब्रेकिंग परिवर्तन नहीं किए जा सकते हैं ।
2. for...of
काम कैसे करता है ?
संदर्भ दस्तावेज़ इस हिस्से के लिए उपयोगी है। विशेष रूप से, किसी ऑब्जेक्ट को माना जाता है iterable
यदि वह Symbol.iterator
संपत्ति को परिभाषित करता है ।
प्रॉपर्टी-डेफिनेशन एक ऐसा फंक्शन होना चाहिए जो कलेक्शन में आई वस्तुओं को, एक, एक करके, और एक झंडे को सेट करता है जो यह दर्शाता है कि लाने के लिए और आइटम हैं या नहीं। पूर्वनिर्धारित कार्यान्वयन कुछ ऑब्जेक्ट-प्रकारों के लिए प्रदान किए जाते हैं , और यह अपेक्षाकृत स्पष्ट है कि for...of
केवल इट्रेटर फ़ंक्शन का उपयोग करता है।
यह दृष्टिकोण उपयोगी है, क्योंकि यह आपके स्वयं के पुनरावृत्तियों को प्रदान करने के लिए बहुत सीधा बनाता है। मैं कह सकता हूं कि दृष्टिकोण एक संपत्ति को परिभाषित करने पर अपनी निर्भरता के कारण व्यावहारिक मुद्दों को प्रस्तुत कर सकता है जहां पहले कोई भी नहीं था, इसके अलावा जो मैं बता सकता हूं कि नई संपत्ति अनिवार्य रूप से नजरअंदाज नहीं की जाती है जब तक कि आप जानबूझकर इसकी तलाश न करें (यानी यह for...in
एक कुंजी, आदि के रूप में छोरों में मौजूद नहीं होगा )। तो ऐसी बात नहीं है।
व्यावहारिक रूप से गैर-मुद्दे एक तरफ, यह सभी वस्तुओं को एक नई पूर्व-निर्धारित संपत्ति के साथ शुरू करने के लिए, या यह कहने के लिए वैचारिक रूप से विवादास्पद माना जा सकता है कि "प्रत्येक वस्तु एक संग्रह है"।
3. वस्तुएं डिफ़ॉल्ट रूप से iterable
उपयोग क्यों नहीं कर रही हैं for...of
?
मेरा अनुमान है कि यह एक संयोजन है:
iterable
डिफ़ॉल्ट रूप से सभी ऑब्जेक्ट बनाना अस्वीकार्य माना जा सकता है क्योंकि यह एक संपत्ति जोड़ता है जहां पहले कोई नहीं था, या क्योंकि कोई वस्तु (जरूरी नहीं) एक संग्रह है। जैसा कि फेलिक्स नोट करता है, "किसी फ़ंक्शन या नियमित अभिव्यक्ति ऑब्जेक्ट पर पुनरावृति करने का क्या मतलब है"?
- सरल वस्तुओं का उपयोग पहले से ही पुनरावृत्त किया जा सकता है
for...in
, और यह स्पष्ट नहीं है कि एक अंतर्निहित पुनरावृत्ति कार्यान्वयन मौजूदा for...in
व्यवहार से अलग / बेहतर तरीके से क्या कर सकता है । इसलिए भले ही # 1 गलत हो और संपत्ति जोड़ना स्वीकार्य था, लेकिन इसे उपयोगी नहीं देखा जा सकता है ।
- जो उपयोगकर्ता अपनी वस्तुओं को बनाना चाहते हैं
iterable
, वे Symbol.iterator
संपत्ति को परिभाषित करके आसानी से ऐसा कर सकते हैं।
- ES6 कल्पना भी एक प्रदान करता मानचित्र प्रकार है, जो है
iterable
डिफ़ॉल्ट रूप से है और एक के रूप में एक सादे वस्तु का उपयोग करने पर कुछ अन्य छोटे फायदे हैं Map
।
संदर्भ प्रलेखन में # 3 के लिए एक उदाहरण भी दिया गया है:
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
for (var value of myIterable) {
console.log(value);
}
यह देखते हुए कि वस्तुओं को आसानी से बनाया जा सकता है iterable
, कि वे पहले से ही इसका उपयोग करके पुनरावृत्त हो सकते हैं for...in
, और यह कि डिफ़ॉल्ट वस्तु पुनरावृत्ति करने वाले को क्या करना चाहिए, इस पर स्पष्ट सहमति नहीं है (यदि यह क्या करता है इसका मतलब किसी भी तरह से अलग for...in
होता है), यह उचित लगता है पर्याप्त है कि वस्तुओं को iterable
डिफ़ॉल्ट रूप से नहीं बनाया गया था।
ध्यान दें कि आपके उदाहरण कोड का उपयोग करके फिर से लिखा जा सकता है for...in
:
for (let levelOneKey in object) {
console.log(levelOneKey);
console.log(object[levelOneKey]);
var levelTwoObj = object[levelOneKey];
for (let levelTwoKey in levelTwoObj ) {
console.log(levelTwoKey);
console.log(levelTwoObj[levelTwoKey]);
}
}
... या आप अपनी वस्तु iterable
को उस तरह से भी बना सकते हैं जिस तरह से आप कुछ ऐसा कर सकते हैं जैसे कि (या आप इसके बजाय असाइन करके सभी ऑब्जेक्ट बना सकते हैं :iterable
Object.prototype[Symbol.iterator]
obj = {
a: '1',
b: { something: 'else' },
c: 4,
d: { nested: { nestedAgain: true }}
};
obj[Symbol.iterator] = function() {
var keys = [];
var ref = this;
for (var key in this) {
keys.push(key);
}
return {
next: function() {
if (this._keys && this._obj && this._index < this._keys.length) {
var key = this._keys[this._index];
this._index++;
return { key: key, value: this._obj[key], done: false };
} else {
return { done: true };
}
},
_index: 0,
_keys: keys,
_obj: ref
};
};
आप यहाँ (क्रोम में, पट्टे पर) के साथ खेल सकते हैं: http://jsfiddle.net/rncr3ppz/5/
संपादित करें
और आपके अपडेट किए गए प्रश्न के जवाब में, हां, ES6 में प्रसार ऑपरेटरiterable
का उपयोग करके, सरणी में कनवर्ट करना संभव है ।
हालाँकि, यह क्रोम में अभी तक काम नहीं कर रहा है, या कम से कम मैं इसे अपने jsFiddle में काम करने के लिए नहीं कर सकता। सिद्धांत रूप में यह उतना ही सरल होना चाहिए:
var array = [...myIterable];
Symbol.iterator
संपत्ति है वह एक चलने योग्य है। तो आपको बस उस संपत्ति को लागू करना होगा। वस्तुएं क्यों न हों, इसके लिए एक संभावित विवरण यह हो सकता है कि इसका अर्थ यह होगा कि सब कुछ पुनरावृत्त था, क्योंकि सब कुछ एक वस्तु है (पाठ्यक्रम के आदिम को छोड़कर)। हालांकि, किसी फ़ंक्शन या नियमित अभिव्यक्ति ऑब्जेक्ट पर पुनरावृति करने का क्या मतलब है?