瞭解

2017-01-17 80 views
3

我有一段代碼:瞭解

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")) 

當你運行它,你將得到下面的輸出:

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

爲什麼結果的第一行不包括A在數組中? 本頁有一個解釋https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*#Passing_arguments_into_Generators。該評論說

下一個的第一次調用()從功能 開始執行,直到第一個yield語句

但是從我的測試看來不正確的。我的測試代碼是:

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()); 

結果是:

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 } 

正如你所看到的,第一next()不僅是第一個yield之前執行的語句,同時也是第一個yield聲明。所以這個理論不能解釋我的問題。任何人都可以幫助我指出正確的方向嗎?提前致謝。

+1

收益運算符必須優先。 –

+1

這很有趣。運行'console.log(gen.next());'首先給出預期的輸出 –

回答

1

考慮你寫的第一個生成器以這種方式重寫。

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"))

是不是更清楚看到爲什麼 「A」 從來沒有被添加到陣列?在數組被修改之前,生成器的第一次執行停在第一個yield語句處。在執行返回到生成器時,傳入值爲「B」。代碼中出現相同的動態array.push(yield array);首先評估內部表達式,因此在訪問push之前yield暫停執行。

我相信,如果您想讓生成器尊重您傳入的第一個值,則需要調用.next(),而無需任何參數。我見過的每個例子都是這樣做的。

另外閱讀this article的「發送」部分說明您的情況。

請注意,此模型適用於問答類型的交互,因爲在提問前我們不能得到答案,並且所有後續的next調用都會​​傳遞前一個問題的答案並檢索下一個問題。

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 

注意,var gen = foo()僅創建一個發生器的一個實例。這是.next()的第一次調用,它啓動發生器的執行。發電機會執行,直至達到yield聲明並返回yield聲明的值。此時,發生器暫停,直到執行另一個.next()調用。

所以,在您的示例中,所有內容都按照預期工作。在第一個示例中,第一個yield語句返回空數組。在下一個.next()該數組填充傳入的值,然後該數組被放棄。在代碼:

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 
} 

這個匹配the documentation

如果可選的值被傳遞給發電機的next()方法時,該值變成由發電機的當前產量操作返回的值。