目前使用最快速的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 = [];
function timer(f, n) {
return function(x) {
var n1 = new Date(), i = n;
do { results.push(f(x)); } while (i-- > 0);
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 毫秒
后退 = 0.04 毫秒
推送 = 0.09 毫秒
Chrome(最新版本,v27):
前进 = 0.07 毫秒
后退 = 0.022 毫秒
推送 = 0.064 毫秒
(作为比较,当结果未存储时,Chrome 产生以下数字:
前进 = 0.032 毫秒
后退 = 0.008 毫秒
推送 = 0.022 毫秒
这比正向数组快近四倍,比push快近三倍。)
IE 10:
前进 = 0.028 毫秒
后退 = 0.012 毫秒
推送 = 0.038 毫秒
奇怪的是,Firefox 仍然显示推送更快。当使用push时,Firefox 应该在后台进行一些代码重写,因为在纯、未增强的 JavaScript 性能方面,访问属性和调用函数都比使用数组索引慢。