迭代器 iterator Symbol.iterator

508 阅读1分钟

迭代器

JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set。这样就需要一种统一的接口机制,来处理所有不同的数据结构。遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)

Iterator的作用

  • 为各种数据结构,提供一个统一的、简便的访问接口;
  • 使得数据结构的成员能够按某种次序排列
  • ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of使用,也就是说prototype需要有[Symbol.iterator]。

原生具备iterator接口的数据(可用for of遍历)

  • Array
  • set容器
  • map容器
  • String
  • 函数的 arguments 对象

注意普通对象不能用迭代器 // 会报Uncaught TypeError: obj is not iterable

当普通对象没有迭代器怎么办?

当普通对象没有 Symbol.iterator属性时

  • 从别的地方借过来使用。
  • 或者我们可以给他造一个
function myIterator(arr) {
       let nextIndex = 0
       return {
         next: function() {
           return nextIndex < arr.length
             ? { value: arr[nextIndex++], done: false }
             : { value: undefined, done: true }
         }
       }
     }
let arr = [1, 4, 'ads']// 准备一个数据
let iteratorObj = myIterator(arr)
console.log(iteratorObj.next()) // 所有的迭代器对象都拥有next()方法,会返回一个结果对象
console.log(iteratorObj.next())
console.log(iteratorObj.next())
console.log(iteratorObj.next())

其实可以让对象都变成可迭代对象, 只需要他们拥有 Symbol.iterator 属性即可

使用for of循环去验证一下即可
​
// 思路1:借助用这个对象的 Symbol.iterator
let obj = {
  0: 200,
  1: 300,
  2: 400,
  length: 3,
}
obj[Symbol.iterator] = Array.prototype[Symbol.iterator]
for (let val of obj) {
  console.log(val)
}
​
let obj = { a: 1 }
Object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]
for (const key of obj) {
  console.log(key)
}
​
// 思路2 自己再去实现一个迭代器规范
Object.prototype[Symbol.iterator] = function() {
  let that = this, // 当前对象
    i = 0,
    keys = Reflect.ownKeys(that)
  // Object.keys(self).concat(Object.getOwnPropertySymbols(self))
​
  return {
    next() {
      console.log(i >= keys.length, keys.length, i, 'i >= length')
      if (i >= keys.length) {
        return {
          value: undefined,
          done: true
        }
      } else {
        return {
          value: [keys[i++]],
          done: false
        }
      }
    }
  }
}
​
let obj = {
  name: 'juice',
  age: 24
}
for (let value of obj) {
  console.log(value)
}

各位看官如遇上不理解的地方,或者我文章有不足、错误的地方,欢迎在评论区指出,感谢阅读。