2016-05-09 4 views
2

Auf Seite der Mozilla iterators and generators gibt es eine Erklärung:Iterator und ein Generator in Javascript?

Während benutzerdefinierte Iteratoren ein nützliches Instrument sind, deren Erstellung erfordert sorgfältige Programmierung aufgrund der Notwendigkeit, ihre internen Zustand explizit zu halten. Generatoren bieten eine leistungsstarke Alternative: Sie ermöglichen Sie einen iterativen Algorithmus zu definieren, indem Sie eine einzige Funktion schreiben, die ihren eigenen Zustand beibehalten kann.

obige Erklärung betrifft, so ist es nicht möglich, einen iterativen Algorithmus ohne Generatoren, wie zu schreiben:

Array[Symbol.iterator] = function(){ 
    return { 
     next: function(){ 
      //logic 
      return { 
       value: "", 
       done:false 
      } 
     } 
    } 
} 

Kann meinen Kopf nicht umgehen. Könnte jemand erklären, was der Hauptgrund ist, warum sie eine Alternative geschaffen haben, scheint mir nicht viel anders zu sein.

+0

'next': ist die Iterationsfunktion für jede Variable im Array. –

+0

Ich empfehle "syntaktischen Zucker" googeln. – zzzzBov

+0

@zzzzBov, in angular2 '#' Charakter ist ein syntaktischer Zucker, aber in seinem Fall glaube ich nicht, – serkan

Antwort

4

Sie können auf der Oberfläche sehr ähnlich aussehen, aber sie können auf sehr unterschiedliche Weise verwendet werden.

Iteratoren und Iterables

Iteratoren sind ziemlich streng definiert: sie sind Gegenstand (den Iteratoren), die enthält eine next (und möglicherweise einige andere) -Funktion. Jedes Mal, wenn die next Funktion aufgerufen wird, wird erwartet, ein Objekt mit zwei Eigenschaften zurück:

  • value: der aktuelle Wert des Iterators
  • done: ist der Iterator fertig?

Ein iterable auf der anderen Seite ist ein Objekt, das eine Eigenschaft mit einem Symbol.iterator Schlüssel hat (das das Symbol gut kennen darstellt @@iterator). Dieser Schlüssel enthält eine Funktion, die beim Aufruf einen neuen Iterator zurückgibt. Ein Beispiel für eine iterable:

const list = { 
    entries: { 0: 'a', 1: 'b' }, 
    [Symbol.iterator]: function(){ 
     let counter = 0; 
     const entries = this.entries; 
     return { 
      next: function(){ 
       return { 
        value: entries[counter], 
        done: !entries.hasOwnProperty(counter++) 
       } 
      } 
     } 
    } 
}; 

Ihr Hauptzweck, wie ihr Name schon sagt, ist eine Schnittstelle zu schaffen, die durchlaufen werden können:

for (let item of list) { console.log(item); } 
// 'a' 
// 'b' 

Generatoren

Generatoren auf die Andererseits sind sie vielseitiger. Es hilft, sie als Funktionen zu betrachten, die pausiert und wieder aufgenommen werden können.

Während sie iteriert werden können (ihre iterables bieten eine next Methode), können sie viel kompliziertere Verfahren implementieren und eine Eingabe/Ausgabe-Kommunikation über ihre next Methode bereitstellen.

Ein einfacher Generator:

function *mygen() { 
    var myVal = yield 12; 
    return myVal * 2; 
} 

const myIt = mygen(); 

const firstGenValue = myIt.next().value; 
// Generator is paused and yields the first value 

const result = myIt.next(firstGenValue * 2).value; 

console.log(result); // 48 

Generator Delegation

Generatoren an einen anderen Generator delegieren kann:

function *mydelgen(val) { 
    yield val * 2; 
} 

function *mygen() { 
    var myVal = yield 12; 
    yield* mydelgen(myVal); // delegate to another generator 
} 

const myIt = mygen(); 
const val = myIt.next().value; 
console.log(val); 
console.log(myIt.next(val).value); 
console.log(myIt.next().value); 

Generatoren & Promises

Generatoren und Promises können zusammen mit Hilfe von Dienstprogrammen wie co eine Art automatischen asynchronen Iterator erstellen.

co(function *(){ 
    // resolve multiple promises in parallel 
    var a = Promise.resolve(1); 
    var b = Promise.resolve(2); 
    var c = Promise.resolve(3); 
    var res = yield [a, b, c]; 
    console.log(res); 
    // => [1, 2, 3] 
}).catch(onerror); 

Im Fazit

Also abschließend könnte man sagen, dass der Hauptzweck der Iteratoren ist eine Schnittstelle zu schaffen für benutzerdefinierte Objekte iteriert werden, während Generatoren eine Fülle von Möglichkeiten für die synchronen bieten und asynchronen Workflows:

  • Stateful Funktionen
  • Generator Delegation
  • Generatoren &
  • CSP

usw.

+0

* "Iteratoren sind ziemlich streng definiert. Sie geben ein Objekt zurück, das eine nächste (und möglicherweise eine andere) Funktion enthält. "Das stimmt nicht. Iteratoren sind Objekte, sie geben nichts zurück. Sie haben eine "nächste" Funktion * selbst *. Oder meinst du * iterables *, anstatt Iteratoren? * "Ein Beispiel für einen Iterator:" * "Liste" ist in Ihrem Beispiel iterierbar. Siehe auch http://www.ecma-international.org/ecma-262/6.0/index.html#sec-iteration. –

+0

@FelixKling danke, diese Begriffe haben mich ein wenig verwirrt. Gibt es einen Namen für die Funktion, die "Symbol.iterator" in einem iterablen zugeordnet ist? – nils

+0

Keiner, den ich kenne ... –

1

verspricht Ist es nicht möglich, einen iterativen Algorithmus ohne Generatoren zu schreiben.

Nein, ist es nicht. Ja, es ist möglich, jeden Generatoralgorithmus als benutzerdefinierten Iterator zu schreiben, aber die // logic in Ihrem Code wird viel komplizierter. Der Schwerpunkt der Aussage ist, dass es nicht mehr iterativ sein wird, es wird rekursiv sein.

Als Übung, hier ist eine ganz einfache iterative Generatorfunktion:

function* traverseTree(node) { 
    if (node == null) return; 
    yield* traverseTree(node.left); 
    yield node.value; 
    yield* traverseTree(node.right); 
} 

Try es als benutzerdefinierten Iterator neu zu schreiben. Ob Sie steckenbleiben oder es schaffen, es wird Ihnen zeigen, was der Unterschied ist.

+0

[Hier ist eine mögliche Lösung] (http://stackoverflow.com/a/23614292/1048572) Ich habe einmal gekritzelt, aber ich bin nicht einmal sicher, ob es korrekt ist. – Bergi

Verwandte Themen