迭代器(Iterator)和生成器(Generation)

一、用生成器给对象定义迭代器

常规方法

const obj = {
  a: 1,
  b: 2,
  c: 3,
  [Symbol.iterator]() {
    let [index, values] = [0, Object.values(this)]
    return {
      next() {
        const done = (index >= values.length)
        const value = done ? undefined : values[index++]
        return {
          done,
          value
        }
      }
    }
  }
}
for (let v of obj) {
  console.log(v) // 1 2 3
}

使用生成器

const obj = {
  a: 1,
  b: 2,
  c: 3,
  *[Symbol.iterator]() {
    let [index, values] = [0, Object.values(this)]
    for (let v of values) {
      yield v
    }
  }
}
for (let v of obj) {
  console.log(v) // 1 2 3
}

生成器(*)实际上是一种返回迭代器的函数。

二、访问默认迭代器

访问数组的默认迭代器

const arr = [1, 2, 3]
const arrIterator = arr[Symbol.iterator]()
console.log(arrIterator.next()) // {value: 1, done: false}
console.log(arrIterator.next()) // {value: 2, done: false}
console.log(arrIterator.next()) // {value: 3, done: false}
console.log(arrIterator.next()) // {value: undefined, done: true}

在引擎中 for-of 循环也是执行了以上类似的处理过程。

三、迭代器和扩展运算符

通过扩展运算符(...)将拥有迭代器的对象转换成一个数组。

const obj = {
  a: 1,
  b: 2,
  c: 3,
  *[Symbol.iterator]() {
    let [index, values] = [0, Object.values(this)]
    for (let v of values) {
      yield v
    }
  }
}
console.log([...obj]) // [1, 2, 3]

四、迭代器和字符串

yield * 可以用于字符串,换言之,就是可以用于拥有迭代器的对象/包装对象。

const strIterator = (function *() {
  yield * 'Hello'
})()
console.log([...strIterator]) // ['H', 'e', 'l', 'l', 'e']

发表评论

您的电子邮箱地址不会被公开。