为什么JavaScript开发者不使用Array.push()?

45

我经常看到开发者在JavaScript中使用以下类似的表达式:

arr = []
arr[arr.length] = "Something"
arr[arr.length] = "Another thing"

“push”更合适,不是吗?

arr = []
arr.push("Something")
arr.push("Another thing")

3
我知道自己只是一个业余爱好者,但我确实使用了“push()”函数,现在感觉好像错过了某些以前不为人知的限制条件... - David Thomas
我经常使用它,尽管我更喜欢一个索引器,在那里它更有逻辑意义(比如一个for循环)。 - Tim M.
有时人们确实认为这样更快。请参阅为什么array.push有时比array[n] = value更快?在添加到数组时使用push方法或.length? - 结果差异如此之大,以至于实际上并不重要。使用更好的方法来理解。 - Bergi
更快的方法是递增索引变量,而不是使用push或在每次迭代中读取增长的array.length。需要注意的是,这种差异对人类来说是可以测量的。 - kennebec
关于这个基准测试,在Chrome中push更快:http://jsben.ch/#/rGPv3 - EscapeNetscape
他们是在2010年之前学习JavaScript和NodeJS的老开发人员。如果你使用现代的ES6 JavaScript进行开发,你会使用push方法。 - Netsab612
7个回答

61

今年年初我曾经问过自己同样的问题。已更新新的测试用例http://jsperf.com/array-push-vs-unshift-vs-direct-assignment/2

在chrome中,push似乎要快得多,在FF中则大致相等。IE9中直接赋值更快,但我很想知道它在IE10中的表现。

我认为大多数开发人员会认为设置数组长度,然后使用直接赋值更快,因为这是大多数编程语言的情况。但JavaScript不同。Javascript数组并不是真正的数组,它们只是像所有其他JavaScript对象一样的键/值映射。因此,预分配实际上是无意义的。

个人而言,我更喜欢使用push(:


我的假设也是关于性能的。在某个时候,避免使用 push() 可能确实更快。但现在不再是这样了!+1 - svidgen
7
在较新版本的Chrome中,直接赋值的速度显著提高。现在,即使使用.length,直接赋值的速度几乎是使用push的两倍。 - AgDude
不,JavaScript 在这里并没有太大的区别。设置数组的长度并使用直接赋值实际上更快(Safari 和 Chrome):https://jsperf.com/push-method-vs-setting-via-key/10 这可能是因为 JavaScript 运行时通常是用 C 实现的,并根据一些启发式算法进行预分配。请参见此处的第 1 和第 2 点:https://www.quora.com/How-are-javascript-arrays-implemented-internally/answer/Kiran-651 - Magne

5
我认为这主要是习惯问题。
一些开发人员之所以使用它,只是因为他们习惯于这样做,并没有考虑到push可能是一种替代方法。
有些开发人员曾经学过一种方法比另一种方法快得多,但没有考虑到JavaScript引擎的最新性能改进。
个人而言,我经常使用push。大多数情况下,可读性和可维护性比性能更重要,至少在性能影响足够小的情况下。这里回答中发布的性能测试显示各种方法之间的性能差异并不大。

+1,确实是这样。而且性能差异不大,每个测试用例和浏览器版本之间的切换也很方便 :-) - Bergi

2
很多时候,当我将一个对象推入数组时,我希望返回该对象的引用。例如:
// Returns object
function createAndAdd(arr) {
  return arr[arr.length] = { id: 1 };
} 
var obj = createAndAdd(arr);

现在我有了新的对象并且已经将其添加到数组中。如果我使用push,那么我将返回数组的长度。它看起来像下面这样:

function createAndAdd(arr) {
  var obj = { id: 1 };
  arr.push(obj);
  return obj;
}

如果对象变得很大,那么代码甚至会变得更丑陋:

function createAndAdd(arr) {
  return arr[arr.push({ id: 1 }) -1];
}

就我个人而言,我喜欢带有立即返回语句的函数。这样做简单易懂,方便查看。非常感谢您提出这个问题。


1

这是一种限制嵌套括号的方法。如果括号太多,你就看不出有多少个或者需要多少个(当以后查看代码时)。我会使用变量,一个人只需要计算一次。

bar = foo.length;
foo[ bar++ ] = "new item 0";
foo[ bar++ ] = "new item 1";
foo[ bar++ ] = "new item 2";
foo[ bar++ ] = "new item 3";

http://jsfiddle.net/vEUU3/


1
我认为这不是关于性能,或者至少不是很重要... 真正重要的是声明式方式与命令式方式之间的区别。

0
Array.prototype.push方法返回更新后的数组长度,而直接声明则返回被分配的值。那是我看到的唯一区别,但我通常会阅读一些有关push方法作为将新值赋给数组的更好方式的最佳实践建议。

0

一些程序员不建议使用array.push(),因为它会修改原始对象。你可以使用扩展运算符代替push()

let arrayOne = [1, 2, 3, 4];

let arrayTwo = arrayOne;

arrayTwo.push(5);

console.log(arrayOne);
console.log(arrayTwo);

// equals to arrayOne before the push()
let arrayOneAux = [1, 2, 3, 4];

// spread operator
let arrayThree = [...arrayOneAux, 5];

console.log(arrayOneAux);
console.log(arrayThree);


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