Generator
1. Konzept
Die Generatorfunktion ist eine von ES6 bereitgestellte asynchrone Programmierlösung, deren Syntaxverhalten sich völlig von herkömmlichen Funktionen unterscheidet.
Generator
Es gibt viele Aspekte des Verständnisses von Funktionen.
- Grammatisch lässt sich zunächst verstehen, dass die Generatorfunktion eine Zustandsmaschine ist, die mehrere interne Zustände kapselt.
- Formal ist eine Generatorfunktion eine gewöhnliche Funktion, weist jedoch zwei Merkmale auf. Zum einen steht zwischen dem Funktionsschlüsselwort und dem Funktionsnamen ein Sternchen; zum anderen werden
yield
Ausdrücke innerhalb des Funktionskörpers verwendet, um verschiedene interne Zustände zu definieren (wasyield
auf Englisch „Ausgabe“ bedeutet).
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
Der obige Code ruft next
die Methode insgesamt viermal auf.
Beim ersten Aufruf wird die Generatorfunktion ausgeführt, bis sie auf den ersten yield
Ausdruck trifft. next
Die Methode gibt ein Objekt zurück, dessen Wertattribut yield
der Wert des aktuellen Ausdrucks ist hello
und done
der Wert des Attributs false
angibt, dass der Durchlauf noch nicht beendet ist.
Beim zweiten Aufruf wird die Generatorfunktion von der Stelle aus ausgeführt, an der der letzte Yield-Ausdruck gestoppt wurde, bis zum nächsten yield
Ausdruck. next
Die von der Methode zurückgegebene Eigenschaft des Objekts value
ist der Wert des aktuellen yield
Ausdrucks world
, und done
der Wert der Eigenschaft false
gibt an, dass der Durchlauf noch nicht beendet ist.
Beim dritten Aufruf wird die Generatorfunktion yield
von der Stelle aus, an der der vorherige Ausdruck aufgehört hat, bis return
zur Anweisung ausgeführt (wenn keine Anweisung vorhanden ist return
, wird sie bis zum Ende der Funktion ausgeführt). next
Die Eigenschaft des von der Methode zurückgegebenen Objekts value
ist return
der Wert des Ausdrucks, der unmittelbar auf die Anweisung folgt (wenn keine return
Anweisung vorhanden ist, value
der Wert der Eigenschaft undefined
), und done
der Wert der Eigenschaft true
gibt an, dass der Durchlauf beendet ist.
Beim vierten Aufruf ist die Ausführung der Generator
Funktion zu diesem Zeitpunkt abgeschlossen und die Eigenschaft next
des von der Methode zurückgegebenen Objekts value
lautet . Wenn Sie die Methode später aufrufen, wird dieser Wert zurückgegeben.undefined
done
true
next
Zusammenfassend lässt sich sagen, dass der Aufruf der Generator-Funktion ein Traverser-Objekt zurückgibt, das den internen Zeiger der Generator-Funktion darstellt. Von nun an wird jedes Mal, wenn eine Methode des Traverser-Objekts aufgerufen wird next
, ein Objekt mit value
und done
zwei Eigenschaften zurückgegeben. value
Das Attribut stellt den Wert des aktuellen internen Status dar, yield
der der Wert des Ausdrucks hinter dem Ausdruck ist; done
das Attribut ist ein boolescher Wert, der angibt, ob der Durchlauf beendet ist.
ES6 legt nicht fest, wo das Sternchen zwischen dem Funktionsschlüsselwort und dem Funktionsnamen geschrieben werden soll. Dies führt zu folgendem Schreiben.
function * foo(x, y) {
··· }k
function *foo(x, y) {
··· }
function* foo(x, y) {
··· }
function*foo(x, y) {
··· }
2. Ertragsausdruck
Die aufrufende next
Methode durchläuft den nächsten internen Status und stellt somit tatsächlich eine Funktion bereit, die die Ausführung unterbrechen kann. yield
Der Ausdruck ist das Pausenflag.
Die Operationslogik der Methode des Traverser-Objekts next
ist wie folgt.
- Wenn ein Yield-Ausdruck gefunden wird, werden die nachfolgenden Vorgänge angehalten und der Wert des Ausdrucks, der unmittelbar auf den Yield folgt, wird als Wertattributwert des zurückgegebenen Objekts verwendet.
- Wenn die nächste Methode das nächste Mal aufgerufen wird, wird die Ausführung fortgesetzt, bis der nächste Ertragsausdruck gefunden wird.
- Wenn kein neuer Yield-Ausdruck gefunden wird, wird er bis zum Ende der Funktion bis zur Return-Anweisung ausgeführt und der Wert des Ausdrucks nach der Return-Anweisung wird als Wertattributwert des zurückgegebenen Objekts verwendet.
- Wenn die Funktion keine Return-Anweisung hat, ist das Wertattribut des zurückgegebenen Objekts undefiniert.
function* gen() {
yield 123 + 456;
}
Im obigen Code wird yield
der folgende Ausdruck 123 + 456
nicht sofort ausgewertet, sondern erst ausgewertet, next
wenn die Methode den Zeiger auf diesen Satz bewegt.