JavaScript如何实现迭代器_生成器函数如何工作?

JavaScript迭代器和生成器是为统一遍历设计的机制:迭代器提供next()方法返回{value,done},生成器函数(function*)用yield简化迭代器创建;对象实现[Symbol.iterator]()即符合迭代器协议。

JavaScript 中的迭代器和生成器函数,本质是为统一遍历行为而设计的语言机制。迭代器对象提供 next() 方法,返回 { value, done } 形式的结构;生成器函数则是创建迭代器的便捷语法糖,用 function* 声明,内部用 yield 暂停执行并产出值。

迭代器协议:手动实现一个迭代器

任何对象只要拥有符合规范的 [Symbol.iterator]() 方法,并返回一个带 next() 的对象,就是可迭代的。

例如,让一个普通对象支持 for...of

const myRange = {
  from: 1,
  to: 3,
  [Symbol.iterator]() {
    let current = this.from;
    return {
      next() {
        if (current <= this.to) {
          return { value: current++, done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

for (const num of myRange) console.log(num); // 1, 2, 3

生成器函数:用 yield 控制暂停与恢复

生成器函数调用后不立即执行,而是返回一个迭代器对象。每次调用 next(),函数从上次暂停处继续,直到下一个 yield 或结束。

关键点:

  • yield 表达式本身有返回值,可通过下一次 next(arg) 传入参数接收
  • 函数内 return 会令 done: true,其值作为最终 value
  • 可配合 for...of、扩展运算符([...gen()])、解构等使用

常见用途:惰性求值与异步流程简化

生成器天然适合处理大数据流或分步任务:

  • 无限序列(如斐波那契):只在需要时计算下一项
  • 读取文件行、处理分页 API:每调用一次 next() 获取一页数据
  • co 库或自定义 runner 结合,实现类似 async/await 的同步写法(早于 async/await 出现)

注意边界情况

生成器一旦执行完毕(done: true),后续调用 next() 总是返回 { value: undefined, done: true }throw()return() 方法可用于提前终止或注入错误;不能直接 new 生成器函数——它不是构造器。