array.push(element)vs array [array.length] = element

时间:2013-06-06 02:03:41

标签: javascript arrays optimization

我想知道是否有理由选择

array.push(element)

结束

array[array.length] = element

反之亦然。

Here's a simple example我有一个数组数组,我希望将这些数字的新数组乘以2:

var numbers = [5, 7, 20, 3, 13];

var arr1 = [];
var len = numbers.length;
for(var i = 0; i < len; i++){
    arr1.push(numbers[i] * 2);
}
alert(arr1);

var arr2 = [];
for(var i = 0; i < len; i++){
    arr2[arr2.length] = numbers[i] * 2;
}
alert(arr2);

1 个答案:

答案 0 :(得分:0)

使用当前JavaScript技术,同时使用最少代码的最快方法是先存储最后一个元素,从而分配完整的数组索引,然后在存储元素时向后计数,从而采用附近内存存储位置的优势,并最大限度地减少缓存未命中。

var arr3 = [];
for (var i = len; i>0;){
    i--;
    arr2[i] = numbers[i] * 2;
}
alert(arr2);

请注意,如果在JavaScript引擎的视图中存储的元素数量“足够大”,则该数组将创建为“稀疏”数组,并且永远不会转换为常规平面数组。

是的,我可以支持。唯一的问题是JavaScript优化器在丢弃未使用的计算方面非常积极。因此,为了公平地计算结果,必须存储(临时)所有结果。另一个我认为已经过时的优化,但实际上进一步提高了速度是使用new Array(*length*)预先初始化数组。这是一个老式的技巧,暂时没有区别,但在极端JavaScript引擎优化的时代没有,它似乎再次发挥作用。

<script>
function arrayFwd(set) {
var x = [];
for (var i = 0; i<set.length; i++)
x[x.length] = set[i];
return x;
}

function arrayRev(set) {
var x = new Array(set.length);
for (var i = set.length; i>0;) {
i--;
x[i] = set[i];
}
return x;
}

function arrayPush(set) {
var x = [];
for (var i = 0; i<set.length; i++)
x.push(set[i]);
return x;
}

results = []; /* we'll store the results so that
optimizers don't realize the results are not used
and thus skip the function's work completely */
function timer(f, n) {
return function(x) {
var n1 = new Date(), i = n;
do { results.push(f(x)); } while (i-- > 0); // do something here
return (new Date() - n1)/n;
};
}

set = [];
for (i=0; i<4096; i++)
set[i] = (i)*(i+1)/2;

timers = {
forward: timer(arrayFwd, 500),
backward: timer(arrayRev, 500),
push: timer(arrayPush, 500)
};
for (k in timers) {
document.write(k, ' = ', timers[k](set), ' ms<br />');
}
</script>

Opera 12.15:

前进= 0.12 ms 向后= 0.04毫秒 push = 0.09 ms

Chrome(最新版本,第27版):

前进= 0.07毫秒 向后= 0.022毫秒 push = 0.064 ms

(相比之下,如果未存储结果,Chrome会生成以下数字: 向前= 0.032毫秒 向后= 0.008毫秒 push = 0.022 ms

与推出阵列相比,这几乎快了四倍,而且与推送相比几乎快了三倍。)

IE 10: 向前= 0.028毫秒 向后= 0.012毫秒 push = 0.038 ms

奇怪的是,Firefox仍然表现出更快的推动力。使用push时,必须在Firefox下进行一些代码重写,因为访问属性和调用函数都比使用纯粹的,未增强的JavaScript性能的数组索引慢。