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

ジェネレーターにおける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 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 あり104.0
IteratorResult object instead of throwing あり あり あり29 あり あり あり
Not constructable with new (ES2016) あり あり ?43 あり10 あり
Trailing comma in parameters ? ? ?52 ? ? ?

Firefox特有のメモ

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

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

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

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

関連項目

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

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