【JavaScript】反復処理⑦　反復可能オブジェクト（ジェネレーター）


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/c8b08da4cbaca4809c22

#目的

* 反復処理についての理解を深める

#本題
###1.ジェネレーター

ジェネレーターとはイテレーターを生成するための特殊な関数
→　より簡略化してイテレーターを作成することができる！！

####基本構文

#####イテレーター

````js
// 基本のイテレーターの定義
function genIterator() {
  return {
    next function(){
      return {
        done: true / false,
        value: 値
      }
    }
  }
}
`````

#####ジェネレーター

`````js

// ジェネレーターに書き換え
// functionの後ろに*をつけることでこの関数がジェネレーター関数であることを示している
function* gen(){
  if(ループ継続){
    // 下記のyieldでイテレーターの部分を表す
    // ここでdoneがfalse, value(値)であることを指す
    yield 値;
  } else {
    // ここのreturnでdoneがtrue, value値を表す　→　ループを抜け出す
    return 値;
  }
}
`````

####例1

簡単なジェネレーターの例

````js
function* gen(){
  yield 1; //①
  yield 2; //②
  return 3; //③
}

// 変数にgen()を格納
// ジェネレーター関数を実行することでイテレーターが帰ってくる
const it = gen();
// イテレーターのnextメソッドを使用
console.log(it.next());
console.log(it.next());
console.log(it.next());
// {value: 2, done: false} →　①のyield
// {value: 2, done: false} →　②のyield
// {value: 3, done: true} →　③のyield
// 上記のように出力される
`````

####例2

より実践的な例
前回の記事で作成したイテレーターをジェネレーターに書き換えていく

````js
function genIterator(max = 10){
  let i = 0;

  return{
    next: function(){
      if(i >= max){
        return{
          done: true
        }
      } else {
        return{
          done: false,
          value: i++
        }
      }
    }
  }
}

const it = genIterator();
console.log(it.next());
`````

上記のイテレーターをジェネレーターに書き換えると以下の通りになる

```js
function* genIterator(max = 10){
  let i = 0;
  // whileを使って条件分岐
  while(i < max){
    yield i++;
    }
    // returnは省略可能(i < maxになった時点でループ終了)
    return ;
  }

const it = genIterator(10);

let a = it.next();
while(!a.done){
  // 0から9が出力される
  console.log(a.value);
  a = it.next();
}
`````

####例3

Syｍbolを使って反復可能オブジェクトにする

```js
function* genIterator(max = 10){
  let i = 0;
  while(i < max){
    yield i++;
    }
    return ;
  }

const obj = {
  // SymbolのイテレーターにgenIteratorを追加
  [Symbol.iterator]: genIterator
}
// for...ofを使用して出力しても同じ結果に
// ジェネレーターでは反復可能オブジェクトを作成せずにofの後ろに直接genIteratorを入れて実行しても使える
for(const i of obj){
  console.log(i);
}
``````

ジェネレーターを反復可能オブジェクトに入れることも可能

````js
const obj = {
  [Symbol.iterator]: function* genIterator(max = 10){
    let i = 0;
    while(i < max){
      yield i++;
      }
      return ;
    }
}


for(const i of obj){
  console.log(i);
}
`````

###2.反復可能オブジェクト（ジェネレーター）

####例1

下記の反復可能オブジェクトを使用したイテレーターをジェネレーターに書き換える

イテレーター

`````js
const items = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3'
}

Object.prototype[Symbol.iterator] = function(){
	const keys = Object.keys(this);

	let i = 0;
	let _this = this;
	return{
		next(){
			let key = keys[i++];
		return{
			done: i > keys.length,
			value: [key, _this[key]]
			}
		}
	}
}
````

ジェネレーター

````js
const items = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3'
}

// ジェネレーター関数なのでfunctionの後ろに*をつける
Object.prototype[Symbol.iterator] = function* (){
	// for..inを使用
	// thisはオブジェクトの参照を保持している
	for(let key in this){
		yield [key, this[key]];
	}
}
// 以上で書き換え終了

for(let [k,v] of items){
//itemsのプロパティの値が出力される
	console.log(k, v);
}
`````


今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [Let'sプログラミング JavaScript入門](https://www.javadrive.jp/javascript/)