🐥

JavaScriptイテレータとは

2021/09/20に公開

イテレータとは😀

for ofですでに使っている
for ofは反復可能なオブジェクトを取る => イテレータを持っているオブジェクト

もともとイテレータを持っているオブジェクト
Arrays,Strings.Maps,Sets,Nodelists

配列にあるイテレータを見てみる

const num = [1, 2, 3, 4, 5]
const numsIterator = num[Symbol.iterator]() // functionなので
console.log(numsIterator)

結果

Object [Array Iterator] {}

Arrayはもともとイテレータを持っていることが分かる📝

nextメソッド

イテレータは必ずnextメソッドを持っている

console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())

結果

{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }

doneがtrueになると終了している

for ofと比較

for (const iterator of num) { // よくみるiはイテレータの意味
  console.log(iterator)
}

結果

1
2
3
4
5

同じ結果が得られた

イテレータを作る

イテレータの仕組み😇

function makeIteretaor() {
  return {
    next: function () {
      return {
        value: "値",
        done: false / true
      }
    }
  }
}

作ってみる

function country() {
  let count = 0
  return {
    next: function () {
      count++
      switch (count) {
        case 1:
          return {
            value: 'JP',
            done: false,
          }
        case 2:
          return {
            value: 'US',
            done: false,
          }
        case 3:
          return {
            value: 'DE',
            done: false,
          }
      }
      return {
        done: true,
      }
    },
  }
}

const countryIteretaor = country()
console.log(countryIteretaor.next())
console.log(countryIteretaor.next())
console.log(countryIteretaor.next())
console.log(countryIteretaor.next())
console.log(countryIteretaor.next())

結果

{ value: 'JP', done: false }
{ value: 'US', done: false }
{ value: 'DE', done: false }
{ done: true }
{ done: true }

しかしこのコードだとSymbol.iteratorが存在しないのでfor ofが使えない
country is not a function or its return value is not iterable🔥
Symbol.iteratorを追加する

function country() {
  let count = 0
+ return {
+  [Symbol.iterator]: function () {
      return {
        next: function () {
          count++
          switch (count) {
            case 1:
              return {
                value: 'JP',
                done: false,
              }
            case 2:
              return {
                value: 'US',
                done: false,
              }
            case 3:
              return {
                value: 'DE',
                done: false,
              }
          }
          return {
            done: true,
          }
        },
      }
+   },
+ }
}

for (const iterator of country()) {
  console.log(iterator)
}

結果

JP
US
DE

動作する🤗

例えば

配列に1を足す

let arry = [3, 5, 9, 14]
function addition() {
  let n = -1
  return {
    [Symbol.iterator]: function () {
      return {
        next: function () {
          n++
          if (arry[n]) {
            return {
              value: arry[n] + 1,
              done: false,
            }
          }
          return {
            done: true,
          }
        },
      }
    },
  }
}

for (const iterator of addition()) {
  console.log(iterator)
}

結果

4
6
10
15

Discussion