首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >javascript数组在推送新元素时是如何工作的?

javascript数组在推送新元素时是如何工作的?
EN

Stack Overflow用户
提问于 2011-08-23 01:23:08
回答 2查看 226关注 0票数 7

我在Chrome / Firefox中测试了这段代码:

代码语言:javascript
复制
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的结果。

EN

回答 2

Stack Overflow用户

发布于 2011-08-23 01:30:54

为什么新的Array(N)是最慢的?

代码语言:javascript
复制
console.log(arr0.length);
console.log(arr1.length);
console.log(arr2.length);

1000000
1000000
2000000
票数 6
EN

Stack Overflow用户

发布于 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.

  • Repeat,。
  1. 是调用O的[ argument.
  2. Let ]内部方法的结果,参数为"length".
  3. Let n be ToUint32(lenVal).
  4. Let items是一个内部列表,其元素按从左到右的顺序是传递给此函数invocation.
  5. Repeat,的参数当items不为空时,从items中删除第一个元素,并让E是带有参数1.

(N),E,true.

  1. Increase n的O的[Put]内部方法的值ToString(n),E,ToString

true.

  • Return

  • 使用参数"length“、n和Put n调用O的[Put]内部方法。

也就是说,实现方式可以有所不同。正如你从Firefox和Chrome的不同中看到的,Chrome似乎在内部优化了数组结构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7151097

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档