導入
ジェネレータは、値を一度に全部作るのではなく、必要になるたびに1つずつ生み出せる特別な関数です。function* と yield で書きます。大きな列や無限の列を、メモリを使いすぎずに扱えます。
説明
function*(アスタリスク付き)で定義し、yield で値を1つ返していったん止まります。次に呼ばれると続きから再開します。
function* countUp(limit) {
for (let i = 1; i <= limit; i++) {
yield i; // ここで一時停止して値を返す
}
}
for (const n of countUp(3)) {
console.log(n); // 1, 2, 3 と順に出る
}
for...of で回すと、yield された値が順番に取り出せます。手動で進めるなら .next() を使い、.value に値が入ります。
function* ids() {
let id = 100;
while (true) { // 無限でも、必要な分だけ取り出せる
yield id++;
}
}
const gen = ids();
console.log(gen.next().value); // 100
console.log(gen.next().value); // 101
console.log(gen.next().value); // 102
普通の関数は最後まで一気に走りますが、ジェネレータは yield で止まって値を返せるのが決定的な違いです。ID発行や、条件を満たすまで値を作り続ける処理などに向いています。
やってみよう
countUp の上限を変えたり、ids を .next() で何度か進めて番号が増えていくのを確かめましょう。
演習
ジェネレータ evens を定義し、2・4・6 を順に yield してください。for...of で合計を求めて表示します。
ヒント1を見る
function* evens(){ yield 2; yield 4; yield 6; } let sum = 0; for (const n of evens()) sum += n; console.log(sum);