Kodokon kodokon.com

इटरेटर, जनरेटर और इटरेशन प्रोटोकॉल

for...of, spread और डिस्ट्रक्चरिंग के पीछे के प्रोटोकॉल में महारत हासिल करें, फिर आलसी अनुक्रम बनाने के लिए जनरेटर का उपयोग करें।

9 मिनट · 3 प्रश्न

इस पाठ को Kodokon में खोलें

दो अलग-अलग प्रोटोकॉल इटरेशन को नियंत्रित करते हैं। कोई वस्तु इटरेबल होती है यदि वह Symbol.iterator कुंजी के अंतर्गत एक मेथड उजागर करती है; उस मेथड को एक इटरेटर लौटाना चाहिए, यानी एक ऐसी वस्तु जिसका next() मेथड { value, done } लौटाता है। जो कुछ भी अनुक्रमों का उपभोग करता है - for...of, spread ऑपरेटर ..., डिस्ट्रक्चरिंग, Array.from, Promise.all - वह इन प्रोटोकॉल से होकर गुजरता है। इसलिए आप किसी भी वस्तु को अनुकूल बना सकते हैं।

JAVASCRIPT
const range = {
  from: 1,
  to: 3,
  [Symbol.iterator]() {
    let current = this.from;
    const last = this.to;
    return {
      next() {
        return current <= last
          ? { value: current++, done: false }
          : { value: undefined, done: true };
      }
    };
  }
};

console.log([...range]); // [1, 2, 3]
बिना किसी क्लास या जनरेटर के, हाथ से लिखा गया एक इटरेबल।

हाथ से इटरेटर लिखना बहुत लंबा होता है। जनरेटर (function*) स्वचालित रूप से एक इटरेटर बनाते हैं: प्रत्येक yield निष्पादन को निलंबित करता है और फ़ंक्शन की स्थानीय स्थिति को संरक्षित रखता है। यह आलसी मूल्यांकन (lazy evaluation) आपको अनंत अनुक्रमों को मॉडल करने देता है, बशर्ते कोई उपभोक्ता माँगे गए मानों की संख्या को सीमित करे।

JAVASCRIPT
function* naturals() {
  let n = 0;
  while (true) yield n++;
}

function* take(iterable, count) {
  let index = 0;
  for (const value of iterable) {
    if (index >= count) return;
    yield value;
    index += 1;
  }
}

console.log([...take(naturals(), 4)]); // [0, 1, 2, 3]
एक अनंत अनुक्रम जिसका उपभोग बिना कभी अवरुद्ध हुए किया जाता है।

जनरेटर इटरेटर return() और throw() भी उजागर करते हैं। एक स्पेक विवरण जो अक्सर अनदेखा रह जाता है: जब आप break, return, या किसी अपवाद के साथ for...of लूप छोड़ते हैं, तो इंजन स्वचालित रूप से iterator.return() को कॉल करता है। एक जनरेटर में, यह किसी भी लंबित finally ब्लॉक को चलाता है - किसी संसाधन (फ़ाइल, कनेक्शन, लॉक) को मुक्त करने का आदर्श स्थान।

JAVASCRIPT
function* readLines() {
  try {
    yield "line 1";
    yield "line 2";
  } finally {
    console.log("cleanup");
  }
}

for (const line of readLines()) {
  console.log(line);
  break; // triggers return(), hence the finally
}
// line 1, cleanup
break, return() को कॉल करता है: finally ब्लॉक चलता है।

ज्ञान जांच

सुनिश्चित करें कि आपको इस पाठ के मुख्य बिंदु याद हैं।

  1. प्रोटोकॉल के अर्थ में किसी वस्तु को इटरेबल क्या बनाता है?
    • एक length प्रॉपर्टी और संख्यात्मक अनुक्रमणिकाओं का होना
    • एक Symbol.iterator मेथड उजागर करना जो next() वाली वस्तु लौटाता है
    • Array.prototype से विरासत में मिलना
    • सीधे एक next() मेथड का होना
  2. जब आप किसी जनरेटर का उपभोग कर रहे for...of लूप को break के साथ छोड़ते हैं तो क्या होता है?
    • कुछ खास नहीं, जनरेटर अंतिम yield पर निलंबित रहता है
    • इंजन इटरेटर पर throw() कॉल करता है
    • इंजन return() कॉल करता है, जो जनरेटर के finally ब्लॉक चलाता है
    • जनरेटर अगली पुनरावृत्ति पर शुरुआत से फिर से चलता है
  3. आप किसी अनंत जनरेटर के साथ बिना प्रोग्राम को अवरुद्ध किए काम क्यों कर सकते हैं?
    • इंजन स्वचालित रूप से पुनरावृत्तियों की संख्या को सीमित कर देता है
    • जनरेटर एक अलग थ्रेड पर चलते हैं
    • मूल्यांकन आलसी है: प्रत्येक मान की गणना केवल तभी होती है जब next() कॉल किया जाता है
    • मान पहले से गणना किए जाते हैं और इंजन द्वारा कैश किए जाते हैं