为什么使用while循环更快地填充新数组?

Pau*_* S. 6 javascript performance

我正在考虑使用本机方法创建包含默认值的数组的方法,最后结束

function pushMap(length, fill){
    var a = [], b = [];
    a.length = length;
    b.push.apply(b,a);
    return b.map(function(){return fill;});
}
Run Code Online (Sandbox Code Playgroud)

期待它是23比while循环慢倍,作为本机方法必须循环两次而while循环一次,所以我相比它jsperf针对

function whileLengthNew(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}
Run Code Online (Sandbox Code Playgroud)

它实际上慢了1827倍(在Ubuntu上使用Google Chrome进行测试,欢迎使用浏览器/操作系统).

发生了什么导致如此巨大的差异?

Ian*_*and 2

我认为这是由于两个主要因素造成的:

  1. 内存分配——whileLengthNew首先创建一个正确大小的数组,然后对其进行操作,pushMap每次创建一个元素的最终数组map。这可能会导致多次分配,尤其是在源数组很大的情况下。a(创建初始值和数组的方式b基本上是无关紧要的,因为map无论如何都会构建一个新数组来返回 - 它实际上不会改变任何内容b

  2. 函数调用开销——在调用 时map,您正在为数组的每个元素调用一个函数。这涉及相当多的开销;设置激活记录和作用域链、堆栈操作以及传回返回值。-- 所有这些都是为了访问函数内恒定的变量。最重要的是,您已经设置了一个闭包,因此即使访问变量fill也比在whileLengthNew版本中慢。