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

为何用箭头函数访问JavaScript数组比方括号更快?

为什么箭头函数访问TypedArray的速度在Chrome中比直接方括号更快?

这个现象的核心原因在于Chrome的V8引擎对箭头函数和变量捕获的特定优化策略,结合TypedArray的底层访问机制导致的,具体可以拆解为以下几点:

1. V8对箭头函数的内联与常量捕获优化

你的代码中lambda是捕获了模块级const变量array的箭头函数,V8引擎会识别到:

  • array是不可重新赋值的常量(const声明),箭头函数的逻辑完全固定,没有动态变化的可能;
  • 箭头函数的体非常简单,仅返回array[i],符合V8的函数内联优化条件。

引擎会直接把lambda(i)的调用替换为array[i]的直接访问,但关键在于:这个内联过程会提前固化array的类型信息——引擎会确认array是Float32Array类型,并且不会被修改,因此在循环的热路径中,跳过了重复的类型检查和边界验证步骤。

而直接写array[i]时,虽然看起来更直接,但V8在某些情况下会保留对array类型的动态检查(即使你用了const,引擎仍会考虑极端场景下的原型链修改等情况,虽然你的代码里没有,但优化策略的保守性导致了额外开销)。

2. TypedArray的方括号访问的底层差异

TypedArray的方括号访问并不是普通对象的属性访问,它对应底层的内存直接读取,但V8对这种访问的优化逻辑和通过函数内联后的访问略有不同:

  • 直接访问array[i]时,引擎需要执行完整的TypedArray索引访问流程,包括范围检查、类型转换等;
  • 当箭头函数被内联后,引擎会将整个访问逻辑视为一个更“静态”的操作,将类型检查提前到循环外完成,循环内仅保留内存读取的核心操作,从而减少了每一次迭代的开销。

3. Firefox的差异原因

Firefox的SpiderMonkey引擎对TypedArray的方括号访问已经做了更激进的优化,直接在循环中就固化了类型信息并跳过了冗余检查,因此箭头函数的内联优化带来的提升微乎其微(仅2%左右),这也说明不同JS引擎的优化策略存在差异。

验证补充

如果修改代码,把const array改成let array(允许重新赋值),你会发现箭头函数的速度优势会消失——因为V8无法再确定array的引用不会变化,无法进行上述的固化优化,此时箭头函数的调用开销就会显现出来。


附上基准测试代码:

const l = 1e3;
const n = 512 * 512;

const array = new Float32Array(n)
for (let i = 0; i < n; i++)
    array[i] = Math.random();

array.get = function (i) {
    return this[i];
};

const lambda = i => array[i];

class Float32ArrayLike extends Float32Array {
    get(i) {
        return this[i];
    }
}


const arrayLike = new Float32ArrayLike(n);
for (let i = 0; i < n; i++)
    arrayLike[i] = array[i];

for (let r = 0; r < 2; r++) {
    console.log("test", r)

    let t0, s;

    t0 = performance.now();
    s = 0;
    for (let i = 0; i < l; i++)
        for (let i = 0; i < n; i++)
            s += array[i];
    console.log("array[i]        ", Math.round(performance.now() - t0), "ms")

    t0 = performance.now();
    s = 0;
    for (let i = 0; i < l; i++)
        for (let i = 0; i < n; i++)
            s += lambda(i);
    console.log("lambda(i)       ", Math.round(performance.now() - t0), "ms")

    t0 = performance.now();
    s = 0;
    for (let i = 0; i < l; i++)
        for (let i = 0; i < n; i++)
            s += array.get(i);
    console.log("array.get(i)    ", Math.round(performance.now() - t0), "ms")

    t0 = performance.now();
    s = 0;
    for (let i = 0; i < l; i++)
        for (let i = 0; i < n; i++)
            s += arrayLike.get(i);
    console.log("arrayLike.get(i)", Math.round(performance.now() - t0), "ms")

}

内容的提问来源于stack exchange,提问作者Guénaël Dequeker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:45:44