2017-01-17 8 views
3

ich ein Stück Code haben:Verständnis von Javascript des Generators

function * input(){ 
    let array = []; 
    while(true) { 
     array.push(yield array); 
    } 
} 

var gen = input(); 
console.log(gen.next("A")) 
console.log(gen.next("B")) 
console.log(gen.next("C")) 
console.log(gen.next("D")) 

Wenn Sie es ausführen Sie erhalten die folgende Ausgabe:

{ value: [], done: false } 
{ value: [ 'B' ], done: false } 
{ value: [ 'B', 'C' ], done: false } 
{ value: [ 'B', 'C', 'D' ], done: false } 

Warum die erste Zeile des Ergebnisses nicht enthält A im Array? Es gibt eine Erklärung auf dieser Seite unter https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*#Passing_arguments_into_Generators. Der Kommentar sagt

der erste Aufruf von next() vom Start der Funktion , bis die ersten yield-Anweisung ausführt

Aber aus meiner Prüfung scheint es nicht richtig. Mein Testcode lautet:

function* logGenerator() { 
    console.log("before yield in function"); 
    yield 1; 
    console.log("filler 1"); 
    yield 2; 
    console.log("filler 2"); 
    yield 3; 
    console.log("filler 3"); 
} 

var gen = logGenerator(); 

console.log(gen.next()); 
console.log("-----------------"); 
console.log(gen.next()); 
console.log("-----------------"); 
console.log(gen.next()); 
console.log("-----------------"); 
console.log(gen.next()); 

Das Ergebnis ist:

before yield in function 
{ value: 1, done: false } 
----------------- 
filler 1 
{ value: 2, done: false } 
----------------- 
filler 2 
{ value: 3, done: false } 
----------------- 
filler 3 
{ value: undefined, done: true } 

Wie Sie sehen können, die erste next() nicht nur die Anweisungen vor dem ersten yield ausgeführt, sondern auch die erste yield Aussage. Also diese Theorie kann meine Frage nicht erklären. Kann mir jemand helfen, mir die richtige Richtung zu zeigen? Danke im Voraus.

+1

Der Yield-Operator muss Vorrang haben. –

+1

Das ist interessant. running 'console.log (gen.next());' gibt zuerst die erwartete Ausgabe –

Antwort

1

Betrachten Sie den ersten Generator, den Sie auf diese Weise umgeschrieben haben.

function * input(){ 
 
    let array = []; 
 
    while(true) { 
 
     var thingToAdd = yield array; 
 
     console.log(thingToAdd); 
 
     array.push(thingToAdd); 
 
    } 
 
} 
 

 
var gen = input(); 
 
console.log(gen.next("A")) 
 
console.log(gen.next("B")) 
 
console.log(gen.next("C")) 
 
console.log(gen.next("D"))

Ist es nicht klarer zu sehen, warum "A" auf dem Array wird nie hinzugefügt? Die erste Ausführung des Generators stoppt bei der ersten yield-Anweisung, lange bevor das Array geändert wird. Zu dem Zeitpunkt, zu dem die Ausführung zum Generator zurückkehrt, ist der übergebene Wert "B". Die gleiche Dynamik tritt in Ihrem Code hier auf array.push(yield array); Innere Ausdrücke werden zuerst ausgewertet, so dass die yield Ausführung anhält, bevor auf die push zugegriffen wird.

Ich glaube, wenn Sie möchten, dass der Generator den ersten übergebenen Wert berücksichtigt, müssen Sie .next() einmal ohne Parameter aufrufen. Jedes Beispiel, das ich gesehen habe, macht das.

Auch das Lesen der "Senden" -Abschnitt von this article veranschaulicht Ihre Situation.

Beachten Sie, dass dieses Modell gut für eine Frage und Antwort Typ Interaktion funktioniert, da wir keine Antwort haben können, bevor eine Frage gestellt wird, und alle folgenden next Anrufe werden in der Antwort auf die vorherige Frage übergeben und die nächste abrufen.

var q1 = gen.next(); 
console.log(q1); 
var a = userInput(); 
var q2 = gen.next(a); 
console.log(q2); 
var a2 = userInput(); 
... 
0
function * foo() { 
    var i = 0 
    yield i 

    i += 1 
    yield i 

    i += 1 
    i += 2 
    yield i 
} 

var gen = foo() 
console.log(gen.next()) // 0 
console.log(gen.next()) // 1 
console.log(gen.next()) // 4 

bemerken, dass die var gen = foo() nur eine Instanz eines Generators erzeugt. Es ist der erste Aufruf von .next(), der die Ausführung des Generators startet. Generatoren führen aus, bis sie eine yield Anweisung erreichen und den Wert dieser yield Anweisung zurückgeben. An diesem Punkt wird der Generator angehalten, bis ein anderer Aufruf von .next() ausgeführt wird.

So funktioniert alles wie in Ihren Beispielen vorgesehen. Im ersten Beispiel gibt die erste yield Anweisung das leere Array zurück. Auf der nächsten .next() wird das Array mit dem übergebenen Wert gefüllt, und dann wird das Array zurückgegeben. In Code:

function * foo (param) { 
    var array = [] 
    // do nothing with param 
    yield array 

    array.push(param) // 'B' 
    yield array 

    array.push(param) // 'C' 
    yield array 

    array.push(param) // 'D' 
    yield array 
} 

Das passt the documentation:

Wenn ein optionaler Wert zum nächsten des Generators geleitet wird() Methode, wird dieser Wert um den Wert des durch den Generatorstromausbeute Betrieb zurückgeführt.

Verwandte Themen