ECMAScript 2015: लूप्स के लिए कास्ट


84

नीचे दिए गए दोनों (या दोनों में से कोई भी) कोड टुकड़े एक पूर्ण ECMAScript 2015 कार्यान्वयन में काम करने वाले होने चाहिए:

for (const e of a)

for (const i = 0; i < a.length; i += 1)

मेरी समझ से, पहला उदाहरण काम करना चाहिए क्योंकि eप्रत्येक पुनरावृत्ति के लिए प्रारंभ किया गया है। यह भी iदूसरे संस्करण के लिए मामला नहीं होना चाहिए ?

मैं उलझन में हूं क्योंकि मौजूदा कार्यान्वयन (बैबेल, IE, फ़ायरफ़ॉक्स, क्रोम, ESLint) constदो लूप वेरिएंट के विभिन्न व्यवहारों के साथ संगत नहीं लगते हैं और पूरी तरह से लागू होते हैं ; मैं भी मानक में एक ठोस बिंदु नहीं ढूंढ पा रहा हूं, इसलिए इसकी बहुत सराहना की जाएगी।


1
const कॉन्स्टेंट xx के लिए है, आपको इसके बजाय उपयोग करना चाहिए
Patsy Issa

3
@JamesThorpe नहीं, मेरा सवाल बस यह स्पष्ट करने की कोशिश करता है कि व्यवहार क्या होना चाहिए। उदाहरण के लिए, ESLint पहला उदाहरण ठीक मानता है (और prefer-constविकल्प के साथ पसंद किया गया ) और दूसरा एक अमान्य। अधिकांश ब्राउज़र कार्यान्वयन दोनों उदाहरणों को अमान्य मानते हैं।
एड्रियनप

4
AFAIK पहला है ठीक है क्योंकि यह प्रत्येक पुनरावृत्ति के साथ फिर से आरंभिक है। यह क्रोम में काम करता है।
lyschoening

@lyschoening और यह दूसरे उदाहरण के लिए भी लागू नहीं होना चाहिए?
एड्रियनपप

4
@adrianp निश्चित रूप से दूसरा उदाहरण नहीं है। लूप के लिए नियमित रूप से बराबर है{const i = 0; while(i < a.length) { /* for body */ i += 1}}
lyschoening

जवाबों:


92

निम्नलिखित के लिए लूप काम करता है:

for (const e of a)

ES6 विनिर्देश इस प्रकार है:

ForDeclaration: LetOrConst ForBinding

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames

पाश के लिए जरूरी काम नहीं करेगा:

for (const i = 0; i < a.length; i += 1)

इसका कारण यह है कि घोषणा केवल लूप बॉडी के निष्पादित होने से पहले एक बार मूल्यांकन की जाती है।

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-statement-runtime-semantics-labelledevaluation


3
आप मसौदे से क्यों जुड़ते हैं और अंतिम युक्ति से नहीं? ecma-international.org/ecma-262/6.0/index.html । साथ ही आप forलूप के लिए गलत मूल्यांकन नियम का हवाला दे रहे हैं । const ...अभिव्यक्ति नहीं है। आप के लिए नियम को देखने की जरूरत है for ( LexicalDeclaration Expression ; Expression) Statement
फेलिक्स क्लिंग

@FelixKling के पास अभी भी पुराना लिंक बुकमार्क था। आप मूल्यांकन नियम के बारे में सही हैं। निष्कर्ष अभी भी एक ही होना चाहिए क्योंकि एक अपरिवर्तनीय बंधन बिल्कुल एक बार बनाया जाता है (चरण 5 में)?
lyschoening

4
सही है, लेकिन मुझे लगता है कि सुराग चरण 9 में है। constएस प्रति पुनरावृत्ति नहीं कर रहे हैं।
फेलिक्स क्लिंग

4
for (const e of a)फ़ायरफ़ॉक्स के नवीनतम संस्करण में काम नहीं करता है। मुझे मिल रहा हैSyntaxError: invalid for/in left-hand side
क्रिस_एफ

2
MDN डॉक्स यह भी कहते हैं, "यदि आप ब्लॉक के अंदर वेरिएबल को पुन: असाइन नहीं करते हैं, तो आप लेट के बजाय कास्ट का उपयोग कर सकते हैं।" developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
फिल गिबिन्स

45

मैं इस बार युक्ति का हवाला नहीं दूंगा, क्योंकि मुझे लगता है कि यह समझना आसान है कि उदाहरण से क्या होता है।

for (const e of a) …

मूल रूप से समतुल्य है

{
    const __it = a[Symbol.iterator]();
    let __res;
    while ((__res = __it.next()) && !__res.done) {
        const e = __res.value;
        …
    }
}

सादगी के लिए मैंने इस बात को नज़रअंदाज़ कर दिया है कि अभिव्यक्ति के eलिए एक टीडीज़ेड है a, और विभिन्न __it.return()/ __it.throw(e)कॉल मामले में लूप समय से पहले ( breakया throwशरीर में) बाहर निकल जाता है ।

for (const i = 0; i < a.length; i += 1) …

मूल रूप से के बराबर है

{
    const i = 0;
    while (i < a.length) {
        …
        i += 1;
    }
}

इसके विपरीतlet , एक लूप constमें एक घोषणा को forप्रत्येक लूप पुनरावृत्ति में पुन: घोषित नहीं किया जाता है (और आरंभीकरण को फिर से निष्पादित नहीं किया जाता है)। जब तक आप breakपहले पुनरावृत्ति में नहीं हैं, आपका i +=यहाँ फेंक दिया जाएगा।


मेरे लिए (नोड 5.0.0) लूप के लिए अपेक्षित के रूप में काम नहीं कर रहा है। 'Let a = [1,3,5], b = [] और' for (a) {b.push (e)} का 'मुझे' b == [1, 1, 1] 'के बाद । एक नोड बग, या इच्छित व्यवहार? आपके कोड के अनुसार, मुझे प्रति पुनरावृत्ति के लिए एक नया 'कॉन्स्टेंस ई = __res.value' असाइनमेंट चाहिए।
जुरगेन स्ट्रोबेल

2
@ JürgenStrobel: एक पुरानी नोड बग जहां constहै varकी तरह गुंजाइश और काम पर फेंक नहीं है। सख्त मोड का उपयोग करें।
बेर्गी

मुझे पता है कि यह पुराना है, लेकिन एक मामूली सुधार while ( ( __res = __it.next() ) && !__res.done) {:। अन्यथा __resसमाप्त हो रहा है trueयाfalse
JDB अभी भी मोनिका

@JDB धन्यवाद, निश्चित! अगर आपने अभी-अभी इसे संपादित किया है तो Btw मैं ठीक हो गया होता।
बर्गी

3

आपका दूसरा उदाहरण निश्चित रूप से काम नहीं करना चाहिए क्योंकि iएक बार घोषित किया गया है और प्रत्येक पुनरावृत्ति पर नहीं यह केवल एक फ़ंक्शन है कि लूप की श्रेणी कैसे काम करती है।

आप इसे एक नियमित ब्राउज़र में आज़मा सकते हैं:

for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){
  console.log(otherVar)
  otherVar = "If otherVar was initialized on each iteration, then you would never read me.";
}

यह ऐसी स्थिति constनहीं है जो forछोरों में पूरी तरह से अस्वीकृत है । केवल forयह कि कास्ट को संशोधित करेगा।

ये मान्य हैं:

for(const i = 0;;){ break } 
for(const i = 0; i < 10;){ break; } 

ये अमान्य हैं:

for(const i = 0;;){ ++i; break; } 
for(const i = 0;;++i){ if(i > 0) break; }

मुझे यकीन नहीं है कि ES2015 युक्ति पढ़ने के बाद फ़ायरफ़ॉक्स एक सिंटेक्सएयर क्यों देता है (हालाँकि मुझे यकीन है कि मोज़िला में चतुर लोग सही हैं), ऐसा लगता है कि यह अपवाद को बढ़ाने वाला है:

एक पर्यावरण रिकॉर्ड में एक नया लेकिन बिना इजाजत के अपरिवर्तनीय बंधन बनाएं। स्ट्रिंग मान N बाउंड नाम का पाठ है। यदि S सत्य है, तो इसे प्रारंभ करने से पहले बाइंडिंग के मान को एक्सेस करने का प्रयास करें या इसे शुरू करने के बाद सेट करें, यह हमेशा एक अपवाद को फेंक देगा, संचालन के सख्त मोड सेटिंग की परवाह किए बिना जो कि बाध्यकारी है। एस एक वैकल्पिक पैरामीटर है जो झूठे को परिभाषित करता है।


आप स्रोत का हवाला दिए बिना कैसे कह सकते हैं? ऐसा क्यों होगा constलेकिन इसके लिए नहीं let?
फेलिक्स क्लिंग

@FelixKling आपको किस कथन के लिए उद्धरण की आवश्यकता है? constअपने आप को फिर से असाइन करने की अनुमति नहीं देता है (यह प्रतियोगिता नहीं है) और जैसा कि मेरा उदाहरण स्पष्ट रूप से दर्शाता है कि forचर परिभाषा भाग के लिए कैसे काम करता है उसकी निहित अपेक्षाओं के विपरीत है। के मूल्य को letबदला जा सकता है, यह varदिए गए उदाहरण में कार्यात्मक रूप से बराबर है , लेकिन letसवाल का हिस्सा नहीं है।
किट सुंडे

1
तो आप स्पष्ट रूप से मतलब है कि const iकेवल एक बार घोषित किया है, लेकिन let iनहीं होगा? आपका उदाहरण केवल दिखाता है कि कैसे var iकाम करता है, नहीं const i। चूंकि दोनों के बीच स्पष्ट अंतर है var, constऔर let, मुझे लगता है कि वह सम्मान के साथ कल्पना करते हैं constकि यह बहुत मूल्यवान होगा।
फेलिक्स क्लिंग

1
@FelixKling आप गलत लिख रहे हैं कि मैं क्या टाइप कर रहा हूं। मैं कह रहा हूँ कि लूप के उस भाग में सब कुछ एक बार घोषित किया गया है। तब ओर्थोगोनली constवैल्यू को केवल एक बार सौंपा जा सकता है, रिक्लेयर करने का कोई भी प्रयास constकाम नहीं करेगा। मेरा उदाहरण इस तथ्य को प्रदर्शित करना है कि घोषणा केवल एक बार होती है, प्रश्न पूछने वाला व्यक्ति शब्दार्थ को समझता है constletसमस्या नहीं है, और नहीं, मेरा स्पष्ट रूप से मतलब नहीं था कि आप क्या सुझाव दे रहे हैं, आप गलत हैं।
किट सुंडे

3
चैट में टिप्पणी की गई: यदि आप उपयोग करते हैं let, तो प्रत्येक पुनरावृत्ति की अपनी प्रति प्राप्त होती है i। इस के for(let foo = 0; i < 10; ++i){} बराबर (funtion() { for(var i = 0; i < 10; ++i){ (function(i) { }(i)) } }());है, जहां मैं से आ रहा हूं: letऔर constदोनों ब्लॉक स्कोप हैं। for/inऔर के for/ofलिए एक ही व्यवहार को बेनकाब constऔर let, लेकिन सामान्य forलूप नहीं करता है। यह स्पष्ट रूप से constअलग तरीके से व्यवहार करता है (संभवतः शायद)। आप बस कहते हैं कि यह "एक बार घोषित" है, लेकिन यह बहुत अधिक आईएमओ को सरल करता है।
फेलिक्स क्लिंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.