先追這段程式
Generator 有三個固定名稱。建立 iterator 時還未走訪任何名稱,接着只 next 兩次,看看 visited。
let visited=0;
function* labels(){for(const label of ['Markup','Layout','Scripting']){visited++;yield label;}}
const iterator=labels();const before=visited;const first=iterator.next();const second=iterator.next();
console.log(JSON.stringify({before,first,second,visited}));
{"before":0,"first":{"value":"Markup","done":false},"second":{"value":"Layout","done":false},"visited":2}| 動作 | 傳回記錄 | visited |
|---|---|---|
| labels() | 只建立 iterator | 0 |
| first next() | {value:"Markup",done:false} | 1 |
| second next() | {value:"Layout",done:false} | 2 |
結果為何如此
呼叫 Generator 先取得 iterator,函式內部尚未執行。next 才跑到下一個 yield 並暫停;取兩次便走訪兩項。最後一個 yield 之後再 next 才完成;完成時的 undefined value 欄會被 JSON 省略。
比較另一種寫法
展開 iterator 會取盡剩餘值。變成陣列時,相關工作已一次做完,不能再沿用原本逐次暫停的方式。
let visited=0;function* labels(){for(const label of ['Markup','Layout','Scripting']){visited++;yield label;}}
const iterator=labels();const first=iterator.next();const rest=[...iterator];
console.log(JSON.stringify({first,rest,visited}));
{"first":{"value":"Markup","done":false},"rest":["Layout","Scripting"],"visited":3}試清邊界
next 兩次後,第三、第四次各會傳回甚麼?
查看參考答案
第三次取得 Scripting,done:false;第四次完成,value:undefined、done:true。visited 維持 3。
let visited=0;function* labels(){for(const label of ['Markup','Layout','Scripting']){visited++;yield label;}}
const iterator=labels();iterator.next();iterator.next();const third=iterator.next();const fourth=iterator.next();
console.log(JSON.stringify({third,fourth,finalValueType:typeof fourth.value,visited}));
{"third":{"value":"Scripting","done":false},"fourth":{"done":true},"finalValueType":"undefined","visited":3}