You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何for...of循环比传统for循环慢很多?

为什么for-of循环比传统索引for循环慢近70%?

我搭建了一个简单的基准测试,对比for (const x of arr)和for (let i = 0; i < arr.length; i++)循环的性能,测试用的是包含10000个随机数的数组:

初始化代码

const arr = [...new Array(10000)].map(() => Math.random());

测试用例1:传统索引for循环

let sum = 0;
for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
}

测试用例2:for-of循环

let sum = 0;
for (const x of arr) {
    sum += x;
}

多次重复测试后,结果始终显示for-of循环比传统索引for循环慢近70%(约4.3万次/秒 vs 约15万次/秒)。我已经排除了微基准测试的常见问题(使用大数组),且借助测试框架避免了冷启动影响,想知道这种性能差距的核心原因。


核心原因分析

  • 迭代器协议的额外开销:for-of基于ES6迭代器协议工作,每次循环前需要调用数组的Symbol.iterator方法生成迭代器对象,之后每一轮循环都要调用迭代器的next()方法,每次调用都会返回一个包含value和done属性的对象。这些函数调用和对象创建的开销,在大数组循环时会被显著放大。而传统索引for循环只是简单的索引递增+数组元素访问,没有这些额外的抽象层开销。

  • 引擎优化的差异:传统索引for循环是JavaScript引擎最容易优化的循环模式——固定的起始/终止条件、线性的索引递增逻辑,引擎可以做大量激进优化:比如自动缓存数组长度、消除数组访问的边界检查、甚至通过向量化指令把循环逻辑批量执行。而for-of的迭代器机制逻辑更复杂,引擎很难对其做同等程度的优化,尤其是普通数组的迭代器包装逻辑无法被完全消除。

  • 变量绑定的额外操作:for (const x of arr)在每一轮循环都会创建一个新的块级变量绑定,相比传统for循环直接复用索引变量i、通过索引访问元素的方式,多了一层变量绑定的开销。

内容的提问来源于stack exchange,提问作者Gaurang Tandon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 09:54:20