जावास्क्रिप्ट ईएस 6 में, एक पुनरावृत्त और पुनरावृत्त के बीच अंतर क्या है?


14

क्या एक पुनरावृत्ति एक पुनरावृत्तिकर्ता के समान है, या वे अलग हैं?

ऐसा लगता है, विनिर्देशों से , एक चलने योग्य एक वस्तु है, कहते हैं, objजैसे कि obj[Symbol.iterator]एक फ़ंक्शन को संदर्भित करता है, ताकि जब आह्वान किया जाए, तो एक ऐसी वस्तु लौटाता है जिसमें एक nextविधि होती है जो किसी {value: ___, done: ___}वस्तु को वापस कर सकती है :

function foo() {
    let i = 0;
    const wah = {
        next: function() {
            if (i <= 2) return { value: (1 + 2 * i++), done: false }
            else return { value: undefined, done: true }
        }
    };
    return wah;     // wah is iterator
}

let bar = {}        // bar is iterable

bar[Symbol.iterator] = foo;

console.log([...bar]);             // [1, 3, 5]   
for (a of bar) console.log(a);     // 1 3 5 (in three lines)

इसलिए उपरोक्त कोड में, bariterable है, और wahइटरेटर है, और next()इटरेटर इंटरफेस है।

तो, पुनरावृत्त और पुनरावृत्त अलग-अलग चीजें हैं।

अब, हालांकि, जनरेटर और पुनरावृत्त के एक आम उदाहरण में:

function* gen1() {
    yield 1;
    yield 3;
    yield 5;
}

const iter1 = gen1();

console.log([...iter1]);                           // [1, 3, 5]
for (a of iter1) console.log(a);                   // nothing

const iter2 = gen1();
for (a of iter2) console.log(a);                   // 1 3 5 (in three lines)

console.log(iter1[Symbol.iterator]() === iter1);   // true

उपरोक्त मामले में, gen1जनरेटर है, और iter1पुनरावृत्त है, और iter1.next()उचित काम करेगा। लेकिन iter1[Symbol.iterator]एक फ़ंक्शन देता है iter1, जो कि जब आह्वान किया जाता है, वापस देता है , जो एक पुनरावृत्ति है। तो iter1क्या इस मामले में एक पुनरावृत्त और पुनरावृत्त दोनों है?

इसके अलावा, iter1उदाहरण 1 के ऊपर से अलग है, क्योंकि उदाहरण 1 में चलने योग्य, [1, 3, 5]जितनी बार चाहें उपयोग कर सकते हैं [...bar], जबकि iter1एक चलने योग्य है, लेकिन चूंकि यह खुद को वापस लौटाता है, जो हर बार एक ही पुनरावृत्ति करता है, केवल [1, 3, 5]एक बार देगा।

तो हम कह सकते हैं, एक पुनरावृत्ति के लिए bar, कितनी बार [...bar]परिणाम दे सकते हैं [1, 3, 5]- और जवाब है, यह निर्भर करता है। और क्या पुनरावृति एक पुनरावृत्ति के समान है? और जवाब है, वे अलग-अलग चीजें हैं, लेकिन वे एक ही हो सकते हैं, जब चलने वाला खुद को पुनरावृत्त के रूप में उपयोग करता है। क्या वो सही है?



" तो iter1इस मामले में एक पुनरावृत्त और पुनरावृत्त दोनों है? " - हाँ। सभी देशी पुनरावृत्तियाँ भी स्वंय लौट कर पुन: प्रयोज्य हैं, ताकि आप आसानी से उन निर्माणों में पारित कर सकें जो एक पुनरावृत्ति की अपेक्षा रखते हैं।
बरगी

जवाबों:


10

हाँ, iterables और iterators अलग बातें हैं, लेकिन (जैसे से के रूप में हैं जिन्हें आप स्वयं JavaScript से प्राप्त के सभी सहित, सबसे iterators keysया valuesपर तरीकों Array.prototypeसे विरासत जनरेटर कार्यों से या जनरेटर) % IteratorPrototype% वस्तु है, जो एक है Symbol.iteratorकी तरह विधि इस:

[Symbol.iterator]() {
    return this;
}

नतीजा यह है कि सभी मानक पुनरावृत्तियाँ भी पुनरावृत्तियाँ हैं। इतना है कि आप उन्हें सीधे उपयोग कर सकते हैं, या उन्हें for-ofलूप में उपयोग कर सकते हैं और ऐसे (जो पुनरावृत्तियों की अपेक्षा करते हैं, पुनरावृत्तियों की नहीं)।

keysसरणियों की विधि पर विचार करें : यह एक सरणी पुनरावृत्ति देता है जो सरणी की कुंजी (इसके अनुक्रमित, संख्या के रूप में) पर जाता है। ध्यान दें कि यह एक पुनरावृत्ति देता है । लेकिन इसका एक सामान्य उपयोग है:

for (const index of someArray.keys()) {
    // ...
}

for-ofएक लेता है iterable , एक नहीं इटरेटर , तो क्यों कि काम करता है?

यह काम करता है क्योंकि पुनरावृत्त भी चलने योग्य है; Symbol.iteratorअभी लौटता है this

यहाँ एक उदाहरण है जो मैं अपनी पुस्तक के अध्याय 6 में उपयोग करता हूँ: यदि आप सभी प्रविष्टियों पर लूप करना चाहते हैं, लेकिन पहले वाले को छोड़ दें और आप sliceउप-भाग को बंद करने के लिए उपयोग नहीं करना चाहते हैं , तो आप इसे पा सकते हैं, पहला मान पढ़ें, फिर एक for-ofलूप को सौंप दें :

const a = ["one", "two", "three", "four"];
const it = a[Symbol.iterator]();
// Skip the first one
it.next();
// Loop through the rest
for (const value of it) {
    console.log(value);
}

ध्यान दें कि यह सभी मानक चलने वाले हैं। कभी-कभी लोग इस तरह से मैन्युअल-कोड किए गए पुनरावृत्तियों के उदाहरण दिखाते हैं:

इटरेटर लौट आने तक rangeनहीं है नहीं एक iterable, तो यह विफल रहता है जब हम साथ इसका इस्तेमाल करने की कोशिश for-of

इसे चलने योग्य बनाने के लिए, हमें या तो इसकी आवश्यकता होगी:

  1. Symbol.iteratorउपरोक्त उत्तर की शुरुआत में विधि जोड़ें , या
  2. इसे% IteratorPrototype% से वारिस करें, जिसमें पहले से ही यह विधि है

अफसोस की बात है, TC39 ने% IteratorPrototype% ऑब्जेक्ट प्राप्त करने का एक सीधा तरीका प्रदान नहीं करने का निर्णय लिया। एक अप्रत्यक्ष तरीका है (एक सरणी से पुनरावृति प्राप्त करना, फिर इसका प्रोटोटाइप लेना, जिसे% IteratorPrototype% के रूप में परिभाषित किया गया है), लेकिन यह एक दर्द है।

लेकिन वैसे भी मैन्युअल रूप से पुनरावृत्तियों को लिखने की आवश्यकता नहीं है; एक जनरेटर फ़ंक्शन का उपयोग करें, क्योंकि जनरेटर यह रिटर्न करने योग्य है:


इसके विपरीत, सभी पुनरावृत्त पुनरावृत्त नहीं होते हैं। Arrays चलने योग्य हैं, लेकिन पुनरावृत्त नहीं। तो तार, नक्शे और सेट हैं।


0

मैंने पाया कि शर्तों की कुछ और सटीक परिभाषाएँ हैं, और ये अधिक निश्चित उत्तर हैं:

ES6 चश्मा और MDN के अनुसार :

जब हम रखते है

function* foo() {   // note the "*"
    yield 1;
    yield 3;
    yield 5;
}

fooजनरेटर फ़ंक्शन कहा जाता है । और फिर जब हमारे पास है

let bar = foo();

barएक जनरेटर वस्तु है । और एक जनरेटर ऑब्जेक्ट पुनरावृत्त प्रोटोकॉल और पुनरावृत्त प्रोटोकॉल दोनों के अनुरूप है

सरल संस्करण इट्रेटर इंटरफ़ेस है, जो सिर्फ एक .next()विधि है।

चलने योग्य प्रोटोकॉल है: ऑब्जेक्ट के लिए obj, obj[Symbol.iterator]"शून्य तर्क फ़ंक्शन देता है जो ऑब्जेक्ट लौटाता है , पुनरावृत्त प्रोटोकॉल के अनुरूप है"।

MDN लिंक के शीर्षक से , यह भी लगता है कि हम एक जनरेटर ऑब्जेक्ट को "जनरेटर" भी कह सकते हैं।

ध्यान दें कि निकोलस ज़कस की पुस्तक अंडरस्टैंडिंग ECMAScript 6 में , उन्होंने संभवतः "जनरेटर" के रूप में "जनरेटर फ़ंक्शन" और "जनरेटर वस्तु" को "पुनरावृत्तिकर्ता" कहा है। ले दूर बिंदु है, वे वास्तव में दोनों "जनरेटर" से संबंधित हैं - एक जनरेटर फ़ंक्शन है, और एक जनरेटर ऑब्जेक्ट या जनरेटर है। जेनरेटर ऑब्जेक्ट पुनरावृत्त प्रोटोकॉल और पुनरावृत्त प्रोटोकॉल दोनों के अनुरूप है।

यदि यह पुनरावृत्ति प्रोटोकॉल के अनुरूप सिर्फ एक वस्तु है, तो आप उपयोग या नहीं कर सकते । यह एक ऐसी वस्तु होनी चाहिए जो चलने योग्य प्रोटोकॉल के अनुरूप हो ।[...iter]for (a of iter)

और फिर, एक नया Iterator वर्ग भी है, भविष्य के जावास्क्रिप्ट स्पेक्स में जो अभी भी एक ड्राफ्ट में है । यह इस तरह के रूप उपाय अपना सकते हैं एक बड़ा इंटरफेस, है forEach, map, reduceवर्तमान सरणी इंटरफ़ेस, और इस तरह के रूप और नए, की take, और drop। वर्तमान पुनरावृत्ति केवल nextइंटरफ़ेस के साथ ऑब्जेक्ट को संदर्भित करता है ।

मूल प्रश्न का उत्तर देने के लिए: एक इटरेटर और एक iterable के बीच अंतर क्या है, इसका उत्तर है: .next()इट्रैटर इंटरफ़ेस के साथ एक ऑब्जेक्ट है , और एक iterable एक objऐसी वस्तु है जो obj[Symbol.iterator]शून्य-तर्क फ़ंक्शन दे सकती है, जो कि, जब बुलाया जाता है, तो एक पुनरावृति देता है।

और एक जनरेटर एक पुनरावृत्त और पुनरावृत्त दोनों है, जो कि जोड़ना है।

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