2016-04-11 16 views
3

In ECMAScript6 ist iterator ein Objekt mit einer next()-Methode, die ein Objekt mit zwei Eigenschaften zurückgibt: {value, done}. Z.B .:Warum brauchen wir sowohl iterierbare als auch Iteratorkonzepte?

function createIterator(ra) { 
    let i = 0; 
    return { 
     next() { 
      if (i < ra.length) 
       return {value: ra[i++], 
         done: false}; 
      else 
       return {value: undefined, 
         done: true}; 
     } 
    }; 
} 

mit einem Iterator erstellt man es nicht sehr nützlich in seinem eigenen Recht findet, ist, da es kein eingebaute Syntax ist Vorteil eines Iterators zu nehmen. Stattdessen muss man Dinge tun, wie:

const it = createIterator(['a', 'b', 'c']); 
    while (true) { 
     const o = it.next(); 
     if (o.done) 
      break; 
     else 
      console.log(o.value); 
    } 

„Iterable“ auf der anderen Seite ist ein Objekt mit einer Symbol.iterator Eigenschaft, dass ein No-Argument Funktion sein muss, die einen Iterator zurückgibt:

function createIterable(ra) { 
    let it = createIterator(ra); 
    return { 
     [Symbol.iterator]() {return it;} 
    }; 
} 

... und wenn wir eine iterable sind wir endlich in der Lage schaffen die for of Syntax: Objekt

for (let v of createIterable(['a', 'b', 'c'])) 
    console.log(v); 

bei dem obigen Code Suche den Mehrwert des „iterable“ über den "Iterator" wird nicht leicht wahrgenommen. Warum benötigt Javascript diese beiden separaten Konzepte von Iterator und Iterator? BTW das ist was Java does as well so muss es einige sprachunabhängige Gründe, warum es eine gute Idee ist, diese beiden unterschiedlichen Konzepte zu haben.

+0

Ein Iterator sollte 'yield', nicht' return' verwenden. Iteratoren implementieren Lazy Evaluation, wie Python-Generatoren und ja, Java. Iterables sind einfach eine Möglichkeit zu standardisieren, wie Sie über Objekte iterieren - dies kommt von C++, wo Iteratoren Iterationen über Objekte standardisieren sollen, bei denen nicht klar ist, was iteriert werden soll. Es gibt eine Welt des Unterschieds. –

+1

Konzeptionell umschließt der "Iterator" den aktuellen Status einer Iterationsoperation und das "iterable" -Symbol kennzeichnet die Sammlung als fähig, einen Iterator bereitzustellen. – Alnitak

+0

@AkshatMahajan Iteratoren und Iterables stehen für sich. Generatoren sind (in dieser Hinsicht) nur eine Annehmlichkeit. –

Antwort

2

Konzeptionell kapselt das Objekt, das die "Iterator" -Schnittstelle implementiert, nur den aktuellen Zustand einer Iterationsoperation ein. Sobald dieser Iterator verbraucht wurde (it.done === true), kann er nicht erneut verwendet werden.

Die Funktion [Symbol.iterator]() eines "iterierbaren" Objekts gibt bei jedem Aufruf einen neuen Iterator zurück.

In dieser Hinsicht ist die OP-Funktion, die möglicherweise fehlerhaft ist, vorsichtig, da das Objekt, das von seiner createIterable-Funktion erstellt wird, nur einen einmaligen Aufruf seiner Symbol.iterator-Funktion ermöglicht. Es würde fehlschlagen, wenn das zurückgegebene Objekt an mehr als eine for .. of Operation übergeben wurde. Idealerweise sollte es lauten:

function createIterable(ra) { 
    return { 
     [Symbol.iterator]() { 
      return createIterator(ra); 
     } 
    } 
} 
+0

@MarcusJuniusBrutus Ich habe meinen Vorbehalt wieder aufgenommen - Ihre 'createIterable' Funktion sollte funktionieren, so dass das zurückgegebene" iterierbare "Objekt wiederverwendet werden kann. – Alnitak

+1

Ja, es ist jetzt in Ordnung. Ich verlasse die Buggy-Implementierung in meiner Frage, da sie für zukünftige Leser steht, da Ihr Vorbehalt entscheidend ist und dazu dient, die Arbeitsteilung zwischen dem Iterablen und dem Iterator hervorzuheben. –

+0

@MarcusJuniusBrutus Ich bin Jetlag - habe nicht realisiert, dass du das OP bist! : p – Alnitak

Verwandte Themen