【JavaScript】反復処理⑤　イテレーター


#はじめに

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

前回の記事

https://qiita.com/nao0725/items/4ec6d1b885b5414c3360


#目的

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

#本題
###1.イテレーター

**イテレーター**とは反復操作を行う際に使用するオブジェクトのこと

**基本構文**

```js
function genIterator(){
  // 下記のgenIteratorに返却されている部分をイテレーターと呼ぶ
  return {
    // イテレーターは必ずnextメソッドを保持する
    next: function(){
      // オブジェクトを返却
      return {
        // ループを継続するかどうか
        done: true/false,
        // 返却する値
        value: 値
      }
    }
  }
}
````

####例1

基本的な使い方

````js
// 関数を準備
// maxというループの上限値を決める引数を設定
function genIterator(max) {
  // 初期値を設定
  let i = 0;

  return {
    next: function(){
      return {
        // falseの場合,ループ継続
        done:  false,
        // ループする度に（nextメソッドが呼ばれる度)1ずつプラス
        value: i++
      }
    }
  }
}

// 動作確認
// 変数itに関数genIteratorを格納
const it = genIterator();
// nextメソッドを使用してdoneとvalueの値が返却される
console.log(it.next());
// 呼ばれる度にvalueの値が増えていく
console.log(it.next());
console.log(it.next());
````

maxの引数に上限値を設定する

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

  return {
    next : function(){
      // if文を使ってループを終了する条件を作る
      // iがmax以上でループ終了
      if(i >= max){
        return{
          // trueの時はvalueの設定いらない
          done: true
        }
      // iがmax以下でループ継続
      } else {
        return {
          done: false,
          value: i++
        }
      }
    }
  }
}

const it = genIterator(10);
// itを初期化
let a = it.next();
// while文の条件として、aがfalseじゃないときループ終了と記載
while(!a.done){
  // 0から9まで出力される
  console.log(a.value);
  // 出力後a初期化(これがないと無限ループ)
  a = it.next();
}
```

####例2

返却される関数をSymbolのイテレーターに追加すると反復可能オブジェクトになる

````js
// このようにmaxに値を渡さないと上限値が設定できない
function genIterator(max = 10){
  let i = 0;

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

// オブジェクトを定義
const obj = {
  [Symbol.iterator]: genIterator
}
// このようにするとobjをfor文で使用できるが、上限値の設定ができないためmax = 10として値を設定した
// for文に追加
for(const i of obj){
  // 0から9まで出力される
  console.log(i);
}
````

上記でループ回数を変更したい場合にはbindを使う

```js
// このようにmaxに値を渡さないと上限値が設定できない
function genIterator(max = 10){
  let i = 0;

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

const obj = {
  // 第一引数はthisの値ですがないのでnull,第二引数にループ回数を設定する
  [Symbol.iterator]: genIterator.bind(null, 100)
}

for(const i of obj){
  // 99まで出力される
  console.log(i);
}
`````

####例3

Setに反復可能オブジェクトを初期値として渡してあげるとインスタンスに対して初期値の設定を行うことができる

````js
// このようにmaxに値を渡さないと上限値が設定できない
function genIterator(max = 10){
  let i = 0;

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

const obj = {
  [Symbol.iterator]: genIterator.bind(null, 5)
}

const set = new Set(obj);
// 0,1,2,3,4,..と出力される
console.log(set);
````

今日はここまで！

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

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