跳至內容
Astera Technology

Generator 未必立即跑,取值才繼續

只取兩個值,核對 Generator 實際做了多少工作。

下載完整個案資料及參考答案 ↓

先追這段程式

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}));
確實的 console 輸出
{"before":0,"first":{"value":"Markup","done":false},"second":{"value":"Layout","done":false},"visited":2}
值與執行位置
動作傳回記錄visited
labels()只建立 iterator0
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}

原始例子檔案