← 返回文章列表
JavaScript·1511 次阅读

迭代器协议与生成器函数

迭代器协议与生成器函数

for...of 背后的协议

能被 for...of 遍历的对象(数组、字符串、Map、Set)都实现了 可迭代协议(Iterable):对象有一个 Symbol.iterator 方法,调用后返回一个迭代器(Iterator)——带 next() 方法的对象:

const arr = ['a', 'b']
const it = arr[Symbol.iterator]()
it.next() // { value: 'a', done: false }
it.next() // { value: 'b', done: false }
it.next() // { value: undefined, done: true }

每次 next() 返回 { value, done },done 为 true 表示遍历结束。展开运算符 ...、解构、Promise.all 之外,new Map()、Array.from 都基于这套协议。

手写一个可迭代对象

const range = {
  from: 1,
  to: 3,
  [Symbol.iterator]() {
    let current = this.from
    return {
      next: () => current <= this.to
        ? { value: current++, done: false }
        : { value: undefined, done: true },
    }
  },
}
console.log([...range]) // [1, 2, 3]

生成器 generator:语法糖利器

手写迭代器很繁琐,function* 生成器会自动返回迭代器,yield 暂停并返回值:

function* rangeGen(from, to) {
  for (let i = from; i <= to; i++) {
    yield i // 每次 next 执行到这里暂停,状态被完整保留
  }
}
const it2 = rangeGen(1, 3)
it2.next() // { value: 1, done: false }

生成器天然可迭代,直接用在 for...of 里。还可以双向传值——next(arg) 的参数会成为上一个 yield 的返回值:

function* quiz() {
  const answer = yield '2 + 2 = ?'
  yield answer === 4 ? '正确' : '错误'
}
const q = quiz()
q.next() // { value: '2 + 2 = ?' }
q.next(4) // { value: '正确' }

实际用途

  • 自定义数据结构支持遍历(链表、树的遍历器)
  • 惰性序列:生成无限数列但只在需要时求值
  • 经典的 redux-saga 用 generator 编排异步副作用
  • async function* 异步生成器 + for await...of:Node 流和分页拉取的优雅写法(如游标翻页 API)

迭代器协议是 ES6 为"如何消费集合"定下的统一接口,理解后看各种语言特性会有串起来的感觉。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4