使用push方法还是.length属性向数组添加元素?

14

做以下这些操作有哪些缺点:

var myArray = [];
myArray[myArray.length] = val1;
myArray[myArray.length] = val2;

改为:

var myArray = [];
myArray.push(val1);
myArray.push(val2);

我确定push方法更加“可接受”,但在功能上有什么区别吗?


这里也有很多混淆。看看这个链接:https://jsperf.com/array-direct-assignment-vs-push - Manohar Reddy Poreddy
7个回答

7

2
我在Firefox中运行了两次测试,结果都显示push速度较慢(约6%)。然而,在Chrome中情况不同(push速度快50%)。此外,使用最新版本的Firefox和Chrome进行测试时,Firefox比Chrome更快(针对此项测试)。 - magallanes
奇怪。对于大多数现代浏览器(Chrome >= 19),length速度更快。请参见jsperf页面上的browserscope框。 - Timothy Gu
@magallanes Chrome 19似乎大大提高了长度方法的性能,因此现在对于小数组来说,它比push()快1.5倍以上。 - Timothy Gu
同意其他人的观点 - 这似乎随着时间的推移而改变,并且取决于浏览器。目前(2016年2月),似乎array[array.length] =在大多数情况下都非常接近(Firefox),或者更快(Chrome,Safari)。我使用的是Mac,所以无法准确测试Windows特定的浏览器。 - Benjamin Robinson

6

在JavaScript中,由于数组没有空洞,所以这两种方法的功能是相等的。而且,使用.push()更加简洁(也更短)。


1
理论上是可以的。但是看看由@AlienWebguy和@naveen制作的jsperf,.push()要慢得多。但无论如何,在现实生活中这种微小的优化可能并不值得太多。 - Timothy Gu

4

我一直认为长度赋值更快。刚刚在Index vs. push performance网站上找到了证据,至少在我的Chrome 14浏览器中,在单次测试运行中是这样的。然而在Chrome中差异不大。


使用的Chrome版本是哪个?你是说推送(第二个测试)比第一个或第三个测试慢吗? - kzh

4
似乎有关于哪个测试在不同的JavaScript引擎中更快的差异。速度上的差异可能是微不足道的(除非需要大量的推送)。在这种情况下,明智的开发人员应该始终偏向可读性。在这种情况下,我和@TheifMaster的意见是[].push()更加简洁易读。代码的维护是编码中最昂贵的部分。

4
提到这点真的很重要:「代码维护是编程中最昂贵的部分。」 - ajax333221

3

根据我的测试,第一种方式更快,我不确定为什么,正在继续研究。此外,ECMA并没有提到哪种方法更好,我认为这取决于浏览器供应商如何实现。

var b = new Array();
var bd1 = new Date().getTime();
for(var i =0;i<1000000; i++){
    b[b.length] = i;
};

alert(new Date().getTime()- bd1);

var a = new Array();
var ad1 = new Date().getTime();
for(var i =0;i<1000000; i++){
    a.push(i);
};

alert(new Date().getTime()- ad1);

你是说 myArray[myArray.length] = val1; 更快吗?你在用什么浏览器? - kzh
结果是:第一个测试用例在Chrome和Firefox中要快得多,但在IE9中稍微慢一些,我没有较低版本的IE;所以总体来说,在这些浏览器中速度更快。 - Howard

2
在JS中,有三种不同的方法可以将元素添加到数组的末尾。它们各自有不同的用例。
1) a.push(v), a.push(v1,v2,v3), a.push(...[1,2,3,4]), a.push(..."test")
在JS中,push()函数并不是一个很好的设计。它返回结果数组的长度,这很愚蠢。因此,在函数式编程中,你永远不能链式使用push()函数,除非你想在最后返回长度。如果它返回调用它的对象的引用,那么即使需要时仍然可以获取长度,例如a.push(..."idiot").length。如果你打算进行函数式编程,请忘记push()函数。
2) a[a.length] = "something"
这是a.push("something")的最大竞争对手。人们为此而争论。对我来说,唯一的两个区别是:
- 它返回添加到数组末尾的值。 - 它只接受单个值。它不像push()函数那样聪明。
如果返回值对你有用,你应该使用它。
3. a.concat(v), a.concat(v1,v2,v3), a.concat(...[1,2,3,4]), a.concat([1,2,3,4])
concat()函数非常方便。你可以像push()函数一样使用它。如果你将参数传递给数组,它会将它们展开到被调用的数组的末尾。如果你将它们作为单独的参数传递,它仍然会做相同的事情,例如a = a.concat([1,2,3],4,5,6); //返回[1, 2, 3, 4, 5, 6]。但是不要这样做,它不太可靠。最好将所有参数都传递给数组字面量。
concat()函数最好的一点是它会返回一个指向结果数组的引用。因此,在函数式编程和链式调用中使用它非常完美。
Array.prototype.concat()是我喜欢的方法。
4) 一个新的push()函数提案
实际上,你可以重写Array.prototype.push()函数,例如:
Array.prototype.push = function(...args) {
                         return args.reduce(function(p,c) {
                                              p[p.length] = c;
                                              return p
                                            }, this)
                       };

这样它就可以完美地返回对其调用的数组的引用。


2
a can be returned with the Comma operator (a.push(v), a) or (a[a.length] = v, a) - Slai

0

我这里有一个更新的基准测试: jsbench.me 随意检查哪个对于你当前的引擎更快。在Chromium 86上,arr[arr.length]arr.push()快了约40%。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接