function* 宣言 (末尾にアスタリスクが付いたfunctionキーワード)は、 Generator オブジェクトを返すジェネレーター関数を定義します。

ジェネレーター関数は、 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

ジェネレーターで文を返す

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"

仕様

仕様 状況 コメント
ECMAScript 2015 (6th Edition, ECMA-262)
function* の定義
標準 初期定義
ECMAScript 2016 (ECMA-262)
function* の定義
標準 ジェネレーターは [[Construct]] トラップを持ってはならず、new と併用された場合は例外を送出するように変更されました。
ECMAScript Latest Draft (ECMA-262)
function* の定義
ドラフト  

ブラウザー実装状況

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本サポート391326 無し2610
IteratorResult object instead of throwing491329 無し 有り 有り
Not constructable with new (ES2016) 有り ?43 無し 有り10
Trailing comma in parameters ? ?52 ? 有り ?
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
基本サポート 有り39 有り26 有り10 ?
IteratorResult object instead of throwing 有り 有り 有り29 有り 有り ?
Not constructable with new (ES2016) 有り 有り ?43 有り10 ?
Trailing comma in parameters ? ? ? ? ? ? ?

Firefox特有のメモ

Firefox26以前のジェネレーターとイテレーター

旧バージョンのFirefoxは旧仕様のジェネレーターを実装しています。旧バージョンでは、 ジェネレーターは大きな違いとして通常の function キーワード(アスタリスクを用いない)を使用して定義されます。 更なる情報はレガシージェネレーター関数を見てください。

スローの代わりにIteratorResultオブジェクトが返される

Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26)からは、完了したジェネレーター関数は TypeError"ジェネレーターはすでに完了しました"をもはやスローしません。かわりに、{ value: undefined, done: true }のような IteratorResult を返します (バグ 958951)。

関連項目

ドキュメントのタグと貢献者

 このページの貢献者: Uemmra3, kdex, kei-itof, chikoski, lv7777, YuichiNukiyama
 最終更新者: Uemmra3,