function* 宣言
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
function*
宣言(function
キーワードにアスタリスクが付いたもの)は、Generator
オブジェクトを返すジェネレーター関数を定義します。
ジェネレーター関数はGeneratorFunction
コンストラクターや、関数式の構文を使用して定義することもできます。
試してみましょう
function* generator(i) { yield i; yield i + 10;}const gen = generator(10);console.log(gen.next().value);// Expected output: 10console.log(gen.next().value);// Expected output: 20
構文
function* name(param0) { statements}function* name(param0, param1) { statements}function* name(param0, param1, /* … ,*/ paramN) { statements}
メモ:ジェネレーター関数には、対応するアロー関数はありません。
引数
name
関数名。
param
省略可関数の形式上の引数の名前。
statements
関数の本体を構成する文。
解説
ジェネレーターは処理を抜け出したり、後から復帰したりすることができる関数です。ジェネレーターのコンテキスト(変数の値)は復帰しても保存されます。
JavaScript のジェネレーターは、特にプロミスと組み合わせることで、非同期プログラミングのための非常に強力なツールとなり、コールバック地獄や制御の逆転などのようなコールバックの問題を、完全に解決できるわけではないものの、軽減することができます。しかし、これらの問題は非同期関数を使用すると、さらにシンプルに解決することができます。
ジェネレーター関数を呼び出しても関数はすぐには実行されません。代わりにその関数のジェネレーターオブジェクトが返されます。イテレーターのnext()
メソッドが呼び出されると、ジェネレーター関数の処理は、イテレーターから返された値を特定する最初のyield
演算子か、ほかのジェネレーター関数に委任するyield*
に達するまで実行されます。next()
メソッドは産出された値を含むvalue
プロパティと、ジェネレーターが最後の値を持つかを真偽値で示すdone
プロパティを持つオブジェクトを返します。引数つきでnext()
を呼び出すと、ジェネレーター関数の実行が再開され、処理が停止していたyield
式をnext()
の引数で置き換えます。
ジェネレーターでreturn
文が実行されると、ジェネレーターが終了します(つまり、それによって返されたオブジェクトのdone
プロパティがtrue
に設定されます)。値が返された場合、それはジェネレーターによって返されたオブジェクトのvalue
プロパティとして設定されます。return
文とよく似ていますが、ジェネレーターの内部でエラーが発生した場合は、ジェネレーターの本体の中でキャッチしない限り、ジェネレーターは終了します。ジェネレーターが終了すると、それ以降のnext()
の呼び出しでは、そのジェネレーターのコードは実行されず、{value: undefined, done: true}
の形のオブジェクトが返されるだけです。
function*
宣言はスコープの先頭に巻き上げられ、そのスコープのどこからでも呼び出すことができます。
例
単純な例
function* idMaker() { let index = 0; while (true) { yield index++; }}const gen = idMaker();console.log(gen.next().value); // 0console.log(gen.next().value); // 1console.log(gen.next().value); // 2console.log(gen.next().value); // 3// …
yield* を使用した例
function* anotherGenerator(i) { yield i + 1; yield i + 2; yield i + 3;}function* generator(i) { yield i; yield* anotherGenerator(i); yield i + 10;}const gen = generator(10);console.log(gen.next().value); // 10console.log(gen.next().value); // 11console.log(gen.next().value); // 12console.log(gen.next().value); // 13console.log(gen.next().value); // 20
ジェネレーターに引数を渡す
function* logGenerator() { console.log(0); console.log(1, yield); console.log(2, yield); console.log(3, yield);}const gen = logGenerator();// 最初の next の呼び出しで、関数の最初から、// 最初の yield 文の前まで実行される。gen.next(); // 0gen.next("pretzel"); // 1 pretzelgen.next("california"); // 2 californiagen.next("mayonnaise"); // 3 mayonnaise
ジェネレーターにおける return 文
function* yieldAndReturn() { yield "Y"; return "R"; yield "unreachable";}const gen = yieldAndReturn();console.log(gen.next()); // { value: "Y", done: false }console.log(gen.next()); // { value: "R", done: true }console.log(gen.next()); // { value: undefined, done: true }
オブジェクトプロパティとしてのジェネレーター
const someObj = { *generator() { yield "a"; yield "b"; },};const gen = someObj.generator();console.log(gen.next()); // { value: 'a', done: false }console.log(gen.next()); // { value: 'b', done: false }console.log(gen.next()); // { value: undefined, done: true }
オブジェクトメソッドとしてのジェネレーター
class Foo { *generator() { yield 1; yield 2; yield 3; }}const f = new Foo();const gen = f.generator();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 }
計算プロパティとしてのジェネレーター
class Foo { *[Symbol.iterator]() { yield 1; yield 2; }}const SomeObj = { *[Symbol.iterator]() { yield "a"; yield "b"; },};console.log(Array.from(new Foo())); // [ 1, 2 ]console.log(Array.from(SomeObj)); // [ 'a', 'b' ]
ジェネレーターはコンストラクターではない
function* f() {}const obj = new f(); // throws "TypeError: f is not a constructor
式で定義されたジェネレーター
const foo = function* () { yield 10; yield 20;};const bar = foo();console.log(bar.next()); // {value: 10, done: false}
ジェネレーターの例
function* powers(n) { //endless loop to generate for (let current = n; ; current *= n) { yield current; }}for (const power of powers(2)) { // controlling generator if (power > 32) { break; } console.log(power); // 2 // 4 // 8 // 16 // 32}
仕様書
Specification |
---|
ECMAScript® 2026 Language Specification # sec-generator-function-definitions |
ブラウザーの互換性
関連情報
function* 式
GeneratorFunction
オブジェクト- 反復処理プロトコル
yield
yield*
Function
オブジェクトfunction
宣言function
式- 関数と関数スコープ
- その他のウェブリソース:
- Regenerator an ES2015 generator compiler to ES5
- Forbes Lindesay: Promises and Generators: control flow utopia — JSConf EU 2013
- Task.js
- Iterating generators asynchronously