为什么push方法比在Javascript中通过数组索引放置值要慢得多

时间:2014-01-10 01:33:15

标签: javascript arrays performance hashtable benchmarking

我很不明白为什么这个测试:

http://jsperf.com/push-method-vs-setting-via-key

显示

 a.push(Math.random());

慢十倍
 a[i] = Math.random();

你能解释为什么会这样吗?什么魔法“推”使它变得如此之慢? (与其他有效的方法相比,这种情况很慢)。

修改

注意:推送测试有偏差。我每次迭代都会增加数组的大小!仔细阅读已接受的答案!

Benchmark results

3 个答案:

答案 0 :(得分:12)

  

你能解释为什么会这样吗?

因为您的测试存在缺陷。 push总是附加到现有的a数组,使其更大,而第二个测试仅使用前1000个索引。 在这里使用setup是不够的,您必须在每个for循环之前重置a数组:http://jsperf.com/push-method-vs-setting-via-key/3

除此之外,对push的方法调用可能有一点开销,与使用for循环的索引相比,确定当前数组长度可能需要额外的时间。

通常有no reason not to use push - 该方法完全适用于该操作,并使某些代码更易于阅读。虽然有些人认为一个版本比另一个版本更快,但两者都在浏览器中同样优化。请参阅Why is array.push sometimes faster than array[n] = value?Using the push method or .length when adding to array? - 结果差异很大,实际上无关紧要。 使用更好的理解。

答案 1 :(得分:3)

这仅仅是因为谷歌决定在优化数组索引方面投入更多工作,而不是优化Chrome中的push方法。

如果你看一下测试结果,现在有更多的人尝试过它,你会发现不同浏览器之间的性能差异很大,甚至在同一浏览器的不同版本之间也是如此。

现在浏览器编译Javascript代码,这意味着浏览器将代码转换为运行解释的Javascript更快的代码。编译器对代码的作用决定了不同的执行方式的执行方式。不同的编译器可以更好地优化某些事物,从而提供不同的性能。

答案 2 :(得分:0)

因为.push()是函数调用而另一个是直接赋值。直接分配总是更快。

请记住,在javascript中,数组就像其他所有对象一样。这意味着您可以直接为它们分配属性。

在数组的特殊情况下,它们具有内置的长度属性,可以在幕后进行更新(以及许多其他优化工具,但现在这并不重要。)

在常规对象中,您可以执行此操作,但它不是数组:

var x = {
   0: 'a',
   1: 'b',
   2: 'c'
};

但是,由于数组和散列都是对象,因此这是等效的。

   var x = [
      'a',
      'b',
      'c'
   ];

由于x是第二种情况下的数组,因此长度会自动计算并可用。