iterator协议本身几乎无运行时开销,性能取决于next()的实现方式:预计算型近o(1),惰性型cpu开销可变,副作用型由i/o决定;实测应直接调用next()并监控内存与耗时。

Iterator 协议本身几乎不带来运行时开销——它只是约定一个 next() 方法返回固定结构的对象,没有强制拷贝、深遍历或同步阻塞逻辑。真正影响性能的,是迭代器背后的实现方式,而非协议本身。
关键开销来源:不是协议,而是实现策略
协议只规定“怎么取下一个值”,但没规定“这个值怎么来”。实际开销取决于你如何实现 next():
-
预计算型迭代器(如
Array.prototype.values()):内部已持有完整数组引用,next()只做索引递增和属性读取,接近 O(1) 时间 + 零额外内存分配; -
惰性计算型迭代器(如生成器函数、自定义 range 迭代器):每次调用
next()才执行一次逻辑(比如计算下一个斐波那契数),CPU 开销取决于该逻辑复杂度,但内存占用恒定; - 副作用型迭代器(如边遍历边发起请求、读文件流):开销由 I/O 或网络决定,协议本身不放大延迟,但可能掩盖瓶颈位置。
评估真实开销的实操方法
别测 for...of 语法糖,要测底层迭代器行为:
- 用
const it = iterable[Symbol.iterator]()拿到原始迭代器; - 连续调用
it.next()1000 次,用console.time()或performance.now()测耗时; - 配合 Chrome DevTools 的 Memory 面板,观察单次
next()是否触发新对象分配(尤其注意频繁创建 {value, done} 对象是否被优化掉); - 对比相同数据下,直接 for 循环索引访问 vs 迭代器访问的帧率稳定性(适用于渲染场景)。
哪些“看起来像开销”的其实是误解
常见误判点:
-
Symbol.iterator 函数调用成本? 它只在首次遍历(或每次新建迭代器)时执行一次,返回迭代器对象。多次
for...of同一对象会各自调用它,但函数体本身通常极轻量; -
done: true 后继续调用 next()? 协议要求后续返回
{value: undefined, done: true},现代引擎对此有高度优化,基本无开销; - 生成器函数比普通函数慢? 是的,但慢在上下文暂停/恢复机制,不是迭代协议。若你不需要暂停能力,手写对象迭代器反而更轻。
性能敏感场景的推荐实践
在 UI 渲染、高频数据处理、嵌入式 JS 环境中:
- 避免在
next()中做 DOM 查询、JSON.parse、正则匹配等重操作; - 对静态数组,优先用原生
arr[Symbol.iterator](),不要包装一层无意义的自定义迭代器; - 需要分块处理大数据时,用生成器 +
yield控制节奏,比一次性生成全量数组再迭代更省内存; - 若迭代逻辑简单且固定(如步进计数),手写闭包迭代器比生成器函数启动更快、内存更少。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











