本文へスキップ
BecomeCoder

JavaScriptコース · 第9章 モダンな書き方 ― 実務のJavaScript · レッスン36

ジェネレータとイテレータ ― 値を少しずつ作る

ブラウザで完結

導入

ジェネレータは、値を一度に全部作るのではなく、必要になるたびに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 を定義し、246 を順に 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);

実際に動かしてみよう

下のエディタにJavaScriptを書いて「実行」を押すと、ブラウザ内のJavaScriptで出力が表示されます。本文の例をそのまま試したり、書き換えたりしてみましょう(console.log の結果が下に出ます。input() を使う回は「標準入力」欄に値を入れてから実行します)。

JavaScript — ブラウザ内で実行

ブラウザ本体のJavaScriptで実行する学習用環境を読み込みます(外部エンジン不要・軽量です)。
スクロールして表示された時点でも自動で読み込まれます。