function\* 宣言
=============

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

ジェネレーター関数は `GeneratorFunction` コンストラクターや、関数式の構文を使用して定義することもできます。

試してみましょう
--------

構文
--


```js
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*` 宣言はスコープの先頭に巻き上げられ、そのスコープのどこからでも呼び出すことができます。

例
-

### 単純な例


```js
function\* idMaker() {
  let index = 0;
  while (true) {
    yield index++;
  }
}

const 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\* を使用した例


```js
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); // 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
```

### ジェネレーターに引数を渡す


```js
function\* logGenerator() {
  console.log(0);
  console.log(1, yield);
  console.log(2, yield);
  console.log(3, yield);
}

const gen = logGenerator();

// 最初の next の呼び出しで、関数の最初から、
// 最初の yield 文の前まで実行される。
gen.next(); // 0
gen.next("pretzel"); // 1 pretzel
gen.next("california"); // 2 california
gen.next("mayonnaise"); // 3 mayonnaise
```

### ジェネレーターにおける return 文


```js
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 }
```

### オブジェクトプロパティとしてのジェネレーター


```js
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 }
```

### オブジェクトメソッドとしてのジェネレーター


```js
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 }
```

### 計算プロパティとしてのジェネレーター


```js
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' ]
```

### ジェネレーターはコンストラクターではない


```js
function\* f() {}
const obj = new f(); // throws "TypeError: f is not a constructor
```

### 式で定義されたジェネレーター


```js
const foo = function\* () {
  yield 10;
  yield 20;
};

const bar = foo();
console.log(bar.next()); // {value: 10, done: false}
```

### ジェネレーターの例


```js
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 Language Specification # sec-generator-function-definitions |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `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