コンテンツにスキップ

JavaScript/Generator

出典: フリー教科書『ウィキブックス(Wikibooks)』


Generator オブジェクトは、JavaScript における非同期処理や反復操作を簡略化するための特殊なオブジェクトです。Generator 関数を使用して生成され、停止と再開を繰り返しながら値を返すことができます。

Generatorオブジェクト

[編集]

Generatorオブジェクトは、ジェネレーター関数を呼び出した際に返されるオブジェクトで、イテレーター (Iterator) として機能します。

Generator関数は、通常の関数とは異なり、function* 構文で定義されます。内部では yield キーワードを使用して、実行を一時停止し、再開することが可能です。

Generator関数を使ったコード例
function* myGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = myGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

特徴

[編集]
  • 停止と再開: Generator関数は、呼び出し元に制御を返しつつ、必要なタイミングで再開できます。
  • 値の生成: yieldを使用して値を順次生成します。
  • 双方向通信: next()メソッドの引数を介して値を渡すことが可能です。

プロパティ

[編集]

Generator.prototype.constructor

[編集]

すべてのジェネレーターオブジェクトは、Generator 関数をコンストラクタとして持ちます。

function* myGen() {}
const gen = myGen();
console.log(gen.constructor === myGen); // true

メソッド

[編集]

Generator.prototype.next(value)

[編集]

yield式の評価を再開し、次のyieldまでの実行結果を返します。

function* naturals() {
  let number = 0;
  for (;;) {
    number++;
    yield number;
  }
}

const gen = naturals();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }

Generator.prototype.return(value)

[編集]

ジェネレーター関数を終了させ、指定された値を返します。

function* myGen() {
  yield 1;
  yield 2;
}

const gen = myGen();
console.log(gen.next());  // { value: 1, done: false }
console.log(gen.return('終わり')); // { value: '終わり', done: true }

Generator.prototype.throw(exception)

[編集]

ジェネレーター内で例外をスローします。

function* myGen() {
  try {
    yield 1;
  } catch (e) {
    console.log('Error caught:', e);
  }
}

const gen = myGen();
console.log(gen.next());  // { value: 1, done: false }
gen.throw(new Error('Something went wrong')); // Error caught: Error: Something went wrong

使用例

[編集]

無限シーケンス

[編集]

ジェネレーターは無限ループを効率的に処理できます。

function* generatePrimes() {
  const primes = [];

  for (let num = 2;; num++) {
    // 素数判定: エラトステネスの篩を簡略化
    let isPrime = true;
    for (const prime of primes) {
      if (num % prime === 0) {
        isPrime = false;
        break;
      }
    }

    if (isPrime) {
      primes.push(num);
      yield num;
    }
  }
}

// ジェネレーターの利用例
const primeGenerator = generatePrimes();

console.log(primeGenerator.next().value); // 2
console.log(primeGenerator.next().value); // 3
console.log(primeGenerator.next().value); // 5

for (const i of primeGenerator.take(8)) {
    console.log(i);
}
/*
11
13
17
19
23
29
31
*/

イテレータとの組み合わせ

[編集]

ジェネレーターはfor...ofループとともに使用することで、シンプルに値を反復処理できます。

function* myGenerator() {
  yield 'A';
  yield 'B';
  yield 'C';
}

for (const value of myGenerator()) {
  console.log(value); // 'A', 'B', 'C'
}

注意事項

[編集]
  • ジェネレーター関数の実行は遅延されます。呼び出しただけでは実行されません。
  • next()を呼び出さない限り、処理は進行しません。

下位階層のページ

[編集]