function* 宣言 (末尾にアスタリスクが付いたfunctionキーワード)は、 Generator オブジェクトを返すジェネレーター関数を定義します。
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
ジェネレーター関数は、 GeneratorFunction コンストラクターを使用して定義することもできます。
構文
function* name([param[, param[, ... param]]]) {
statements
}
name- 関数名。
param- 関数に渡される引数名。引数は255個までもつことが可能。
statements- 関数本体に含まれる命令文。
解説
ジェネレーターは処理を抜け出すことも後から復帰することもできる関数です。ジェネレーターのコンテキスト (変数の値)は復帰しても保存されます。
ジェネレーター関数を呼び出しても関数は直ぐには実行されません。代わりに、関数のためのiterator オブジェクトが返されます。iterator の next() メソッドが呼ばれると、ジェネレーター関数の処理は、イテレーターから返された値を特定する最初のyield演算子か、ほかのジェネレーター関数に委任する yield*に達するまで実行されます。next() メソッドはyieldされた値を含む value プロパティと、ジェネレーターが最後の値を持つかを真偽値で示す done プロパティを持つオブジェクトを返します。 引数つきでnext() を呼ぶとジェネレーター関数の実行が再開され、処理が停止していた yield 式を next() の引数で置き換えます。
return 文はジェネレーターで、実行された時、ジェネレーターを done にします。値が return(返却)されたら、value として返されます。値を返されたジェネレーターは、それ以降は値をyieldしません。
例
単純な例
function* idMaker(){
var index = 0;
while (index < index+1)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.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;
}
var gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
引数をジェネレーターにパースさせる
function* logGenerator() {
console.log(0);
console.log(1, yield);
console.log(2, yield);
console.log(3, yield);
}
var gen = logGenerator();
// 最初の next の呼び出しで、関数の最初から、
// 最初の yield 文の前まで実行される。
gen.next(); // 0
gen.next('pretzel'); // 1 pretzel
gen.next('california'); // 2 california
gen.next('mayonnaise'); // 3 mayonnaise
ジェネレーターにおけるreturn文
function* yieldAndReturn() {
yield "Y";
return "R";
yield "unreachable";
}
var 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 }
ジェネレータをコンストラクタにすることはできません。
function* f() {}
var obj = new f; // throws "TypeError: f is not a constructor"
式中で定義されたジェネレーター
const foo = function* () {
yield 10;
yield 20;
};
const bar = foo();
// {value: 10, done: false}
bar.next();
仕様
| 仕様 | 状況 | コメント |
|---|---|---|
| ECMAScript 2015 (6th Edition, ECMA-262) function* の定義 |
標準 | 初期定義 |
| ECMAScript 2016 (ECMA-262) function* の定義 |
標準 | ジェネレーターは [[Construct]] トラップを持ってはならず、new と併用された場合は例外を送出するように変更されました。 |
| ECMAScript (ECMA-262) function* の定義 |
現行の標準 |
ブラウザー実装状況
| デスクトップ | モバイル | サーバー | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
function* | Chrome 完全対応 39 | Edge 完全対応 13 | Firefox 完全対応 26 | IE 未対応 なし | Opera 完全対応 26 | Safari 完全対応 10 | WebView Android 完全対応 39 | Chrome Android 完全対応 39 | Firefox Android 完全対応 26 | Opera Android 完全対応 26 | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 4.0 | nodejs
完全対応
4.0.0
|
IteratorResult object instead of throwing | Chrome 完全対応 49 | Edge 完全対応 13 | Firefox 完全対応 29 | IE 未対応 なし | Opera 完全対応 36 | Safari 完全対応 10 | WebView Android 完全対応 49 | Chrome Android 完全対応 49 | Firefox Android 完全対応 29 | Opera Android 完全対応 36 | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 5.0 | nodejs 完全対応 あり |
Not constructable with new (ES2016) | Chrome 完全対応 50 | Edge 完全対応 13 | Firefox 完全対応 43 | IE 未対応 なし | Opera 完全対応 37 | Safari 完全対応 10 | WebView Android 完全対応 50 | Chrome Android 完全対応 50 | Firefox Android 完全対応 43 | Opera Android 完全対応 37 | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 5.0 | nodejs 完全対応 あり |
| Trailing comma in parameters | Chrome 完全対応 58 | Edge 完全対応 14 | Firefox 完全対応 52 | IE 未対応 なし | Opera 完全対応 45 | Safari 完全対応 10 | WebView Android 完全対応 58 | Chrome Android 完全対応 58 | Firefox Android 完全対応 52 | Opera Android 完全対応 43 | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 7.0 | nodejs 完全対応 8.0.0 |
凡例
- 完全対応
- 完全対応
- 未対応
- 未対応
- ユーザーが明示的にこの機能を有効にしなければなりません。
- ユーザーが明示的にこの機能を有効にしなければなりません。
Firefox特有のメモ
Firefox26以前のジェネレーターとイテレーター
旧バージョンのFirefoxは旧仕様のジェネレーターを実装しています。旧バージョンでは、 ジェネレーターは大きな違いとして通常の function キーワード(アスタリスクを用いない)を使用して定義されます。 更なる情報はレガシージェネレーター関数を見てください。
スローの代わりにIteratorResultオブジェクトが返される
Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26)からは、完了したジェネレーター関数は TypeError"ジェネレーターはすでに完了しました"をもはやスローしません。かわりに、{ value: undefined, done: true }のような IteratorResult を返します (バグ 958951)。
関連項目
function* 式GeneratorFunctionオブジェクト- The Iterator protocol
yieldyield*Functionオブジェクトfunction 宣言function 式関数と関数スコープ- Other web resources:
- Regenerator an ES2015 generator compiler to ES5
- Forbes Lindesay: Promises and Generators: control flow utopia -- JSConf EU 2013
- Hemanth.HM: The New gen of *gen(){}
- Task.js