我在Chrome / Firefox中测试了这段代码:
console.time('simple push');
var arr0 = [];
for(var i =0; i < 1000000; i++){
arr0.push(i);
}
console.timeEnd('simple push');
console.time('set length and push');
var arr1 = [];
arr1.length=1000000;
for(var j =0; j < 1000000; j++){
arr1[j]=j;
}
console.timeEnd('set length and push');
console.time('new Array push');
var arr2 = new Array(1000000);
for(var k =0; k < 1000000; k++){
arr2[k]=k;
}
console.timeEnd('new Array push');Chrome 13结果
简单推流:59ms
设置长度和推流:192ms
新阵列推送:187ms
Firefox 4结果
简单推流:76ms
设置长度和推流:44ms
新阵列推送:40ms
我的怀疑
所以new Array操作绝对是最慢的,但我想知道为什么?
为什么设置长度在Chrome和Firefox中表现不同,似乎预分配的内存在Chrome中不能很好地工作?
更新
我更新了Chrome和FF的结果。
发布于 2011-08-23 01:30:54
为什么新的Array(N)是最慢的?
console.log(arr0.length);
console.log(arr1.length);
console.log(arr2.length);
1000000
1000000
2000000发布于 2011-08-23 01:49:19
正如您已经意识到的,您的测试用例是有缺陷的。在所有方法中使用赋值的Here is a jsperf test案例。
在Firefox6中,它们的速度都是相同的(大约50000操作/秒)。然而,在Chrome13中,预先设置数组长度会带来巨大的速度提升(约80,000 op/s与约400.000 op/s)。要找到原因,你必须看一看Chrome的JavaScript引擎的源代码。
你问过在.push()和new Array上发生了什么。规范描述了was应该发生的情况:
15.4.2.2 new Array (len)
新构造的对象的[ prototype ]内部属性被设置为原始数组原型对象,即Array.prototype (15.4.3.1)的初始值。新构造的对象的[Class]内部属性设置为“数组”。新构造的对象的[Extensible]内部属性设置为true。
如果参数len是一个数字,并且长度等于len,那么新构造的对象的ToUint32(len)属性将设置为ToUint32(len)。如果参数len是一个数字,并且ToUint32(len)不等于len,则会抛出RangeError异常。
如果参数len不是数字,则新构造对象的length属性设置为1,新构造对象的0属性设置为len,其属性为{[Writable]:true,[Enumerable]:true,[Configurable]:true}。
15.4.4.7 Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )
参数按出现的顺序追加到数组的末尾。数组的新长度将作为调用的结果返回。
当使用零个或多个参数item1、item2等调用push方法时,将执行以下步骤:
items是一个内部列表,其元素按从左到右的顺序是传递给此函数的参数invocation.
(N),E,true.
true.
也就是说,实现方式可以有所不同。正如你从Firefox和Chrome的不同中看到的,Chrome似乎在内部优化了数组结构。
https://stackoverflow.com/questions/7151097
复制相似问题