【javascript】ジェネレータ関数

こちらの記事は以下の書籍を参考に執筆しました

- [入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)

#ジェネレータ関数
```javascript
//ジェネレータ関数にはアスタリスクが付いている。
function *myGeneratorFunction(){
  //...
}

//ジェネレータ関数の呼び出しではnewを使用しない
const myGenerator=myGeneratorFunction()
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)

```javascript
const myObj={
  *myGen(){//オブジェクトリテラルでの簡潔なジェネレータメソッド
    //..
  }
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


##イールディング
ジェネレータ関数内のコードは通常の関数と同じように動作するが、1つ大きな注意点がある。
javascriptでは関数の内側で飲み使える**yield**が追加されている。
これにより関数内側と外側との間に双方向の通信チャンネルが作成される。

関数の実行はyieldが検出されたとことで中断、その関数を呼出した外側のコードに制御が戻される。
yieldを使用するときは、returnと同様に外側のプロセスに値を渡すこともできる。

```javascript
function* myGeneratorFunction(){
  //...
  const message='Hello';
  yield message;//実行はここで中断し、外側のプロセスに'Hello'が返される
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



yieldは実際には式であり、関数内であとから使用する値を取得できる。

```javascript
function* myGeneratorFunction(){
  //...
  const message='Hello';
  yield message;//外側からのプロセスからの値を補足
  //...
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



#ジェネレータ関数の使用
ジェネレータ関数を呼び出すと、新しいジェネレータオブジェクトが返される。このジェネレータオブジェクは最初は停止状態で、nextメソッドを呼び出すまで何もしない。

```javascript
function* myGeneratorFunction() {
  connsole.log('This code is now running')
}

myGeneratorFunction() //この時点ではlogは評価されない

const myGenerator = myGeneratorFunction(); //ここでも評価されない。

myGenerator.next(); //ようやく評価される。
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



yieldがある場合は呼び出しまで何もしない

```javascript
function* myGeneratorFunction() {
  console.log('A')
  yield;
  console.log('B')
}
const myGenerator = myGeneratorFunction();

myGenerator.next(); //A
myGenerator.next(); //B
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


nextメソッドを呼び出すたびにvalueとdoneの2つのプロパティを持つオブジェクトが返される。

|プロパティ|説明|
|---|---|
|value|yieldに渡された値を含んでいる。|
|done|ジェネレータが中断状態7日終了したのかを示す。|
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



```javascript
function* myGeneratorFunction() {
  console.log('Started')
  let recievedA = yield 'a'
  console.log('recievedA:', recievedA)
  let recievedB = yield 'b'
  console.log('recievedB:', recievedB)
}
const myGenerator = myGeneratorFunction();
let gotA = myGenerator.next(0); //Started
console.log('gotA', gotA) //gotA {value: "a", done: false}
let gotB = myGenerator.next(1); //recievedA: 1
console.log('gotB', gotB) //gotB {value: "b", done: false}
let gotC = myGenerator.next(2); //recievedB: 2
console.log('gotC', gotC) //gotC {value: undefined, done: true}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


ジェネレータ関数から最後に返されたオブジェクトのdoneプロパティにはtrueが設定されて、valueがundefinedになっている。

また、最初のnext呼び出しに渡された0が使用されない。これは最初のnextが以降のようにyieldに関連付けられていないため。

最初のnext呼び出しはジェネレータを初期状態から呼び起こすためのもの。

#まとめ

- ジェネレータ関数はアスタリスクで定義
- ジェレネータ関数はジェネレータオブジェクトを返す
- ジェレネータはyieldで値を返せる
- nextで次の処理を実行できる