JavaScript/Generator
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()
を呼び出さない限り、処理は進行しません。