javascript - array.push(element) 与 array[array.length] = element

标签 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);

最佳答案

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

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>

歌剧 12.15:

前进 = 0.12 毫秒 向后 = 0.04 毫秒 推 = 0.09 毫秒

Chrome(最新,v27):

前进 = 0.07 毫秒 向后 = 0.022 毫秒 推送 = 0.064 毫秒

(为了比较,当未存储结果时,Chrome 会生成这些数字: 向前 = 0.032 毫秒 向后 = 0.008 毫秒 推 = 0.022 毫秒

这比做数组前向快了将近四倍,比做推送快了近三倍。)

IE 10: 向前 = 0.028 毫秒 向后 = 0.012 毫秒 推送 = 0.038 毫秒

奇怪的是,Firefox 仍然显示推送速度更快。当使用推送时,Firefox 必须在后台进行一些代码重写,因为就纯的、未增强的 JavaScript 性能而言,访问属性和调用函数都比使用数组索引慢。

关于javascript - array.push(element) 与 array[array.length] = element,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16952605/

相关文章:

C# 轻量级方法来存储具有快速访问的大位矩阵

javascript - 如何更快地匹配此文本?

javascript - 测试用 Jest 覆盖 console.log

Javascript:某些类在 2 个 javascripts/ccs 中以相同的名称定义了两次

javascript - 用于在 Google Maps v3 上创建多条路线的数组

python - 我可以在不复制数据的情况下组合 NumPy 数组中的非相邻维度吗?

optimization - 我可以强制 Rust 不优化单个函数吗?

javascript - 如何在执行 event.preventDefault() 后重新启用默认值

javascript - Navigator.sendBeacon() 传递头信息

javascript - js 与数组匹配搜索