javascript迭代器是什么以及如何工作_generator函数有何用途【教程】

11次阅读

javaScript迭代器是约定含next()方法并返回{value, done}对象接口;数组等内置类型需先调用[symbol.iterator]()获取迭代器;Generator函数返回可暂停恢复的迭代器,适用于无限序列、异步建模和状态机。

javascript迭代器是什么以及如何工作_generator函数有何用途【教程】

javascript 迭代器接口长什么样

迭代器不是语法糖,而是一个**约定好的对象接口**:只要一个对象有 next() 方法,且该方法返回形如 { value: any, done: Boolean } 的对象,它就是迭代器。数组、字符串map、Set 默认提供 [Symbol.iterator]() 方法,调用后才得到真正的迭代器对象。

常见错误是直接对数组调用 next()[1,2,3].next() 会报 TypeError: undefined is not a function —— 因为数组本身不是迭代器,得先调用 [1,2,3][Symbol.iterator]() 才行。

实际使用中,for...of、解构赋值(const [a, b] = arr)、扩展运算符[...arr])都会自动调用 [Symbol.iterator] 并消费迭代器,你通常不需要手动写 next() 调用链。

Generator 函数本质是迭代器工厂

function* 声明的 generator 函数不立即执行,而是返回一个迭代器对象。每次调用它的 next(),函数体从上次暂停处(yield)继续运行,直到下一个 yield 或函数结束。

立即学习Java免费学习笔记(深入)”;

关键点:

  • yield 后面的表达式只在 next() 被调用时求值,支持惰性计算
  • next() 可传参,该参数会成为上一个 yield 表达式的返回值(常用于双向通信)
  • generator 函数内部可使用 throw()return() 控制流程,但多数场景只需 next()

示例:

function* countdown(n) {   while (n > 0) yield n--; } const it = countdown(3); it.next(); // { value: 3, done: false } it.next(); // { value: 2, done: false } it.next(); // { value: 1, done: false } it.next(); // { value: undefined, done: true }

Generator 真正有用的三个场景

别把它当“高级 for 循环”用。generator 的价值在于**状态保持 + 暂停恢复 + 异步建模**:

  • 无限序列生成:比如斐波那契、素数筛,用普通函数必须预分配数组;generator 可按需产出,内存零压力
  • 异步流程控制(ES2017 前):配合 co 或手写 runner,把 yield promise 当作 await 用(注意:现在应优先用 async/await
  • 状态机封装:比如一个分步骤表单校验器,每步 yield 校验结果,外部用 next() 推进,比一回调或 Promise 链更直观

容易忽略的是:generator 函数返回的迭代器对象本身是可遍历的,所以也能被 for...of 消费 —— 这让它的使用边界变得很自然,不用纠结“该不该手动调 next”。

为什么不能用普通函数模拟 generator

核心在于**执行上下文不可恢复**。普通函数一旦 return帧销毁,局部变量全丢;而 generator 函数被 yield 暂停时,整个执行上下文(作用域链、变量、指令指针)都被保留下来,下次 next() 时原样恢复。

这意味着你无法靠闭包 + 计数器安全复现 generator 行为:比如多次调用同一 generator 实例,每次都是独立状态;但闭包模拟的“迭代器”若没做深拷贝或重置逻辑,状态会互相污染。

还有兼容性细节:generator 是 es6+ 特性,IE 完全不支持;若需兼容旧环境,必须 Babel 编译(转成基于 regeneratorRuntime 的状态机),而这个 runtime 本身有体积和性能开销——不是所有“看起来像迭代”的地方都值得上 generator。

text=ZqhQzanResources