为什么arr = 比arr = new Array快?

我运行这个代码,得到了下面的结果。 我很想知道为什么[]更快?

 console.time('using[]') for(var i=0; i<200000; i++){var arr = []}; console.timeEnd('using[]') console.time('using new') for(var i=0; i<200000; i++){var arr = new Array}; console.timeEnd('using new') 
  • 使用[] :299ms
  • 使用new :363ms

感谢Raynos这里是这个代码的基准和一些更可能的方式来定义一个variables。

在这里输入图像描述

进一步扩大以前的答案…

从一般编译器的angular度来看,不考虑特定于虚拟机的优化:

首先,我们通过词法分析阶段来标记代码。

举例来说,可以生成以下令牌:

 []: ARRAY_INIT [1]: ARRAY_INIT (NUMBER) [1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER) new Array: NEW, IDENTIFIER new Array(): NEW, IDENTIFIER, CALL new Array(5): NEW, IDENTIFIER, CALL (NUMBER) new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER) new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER) 

希望这应该为您提供足够的可视化,以便您了解需要多less(或更less)处理。

  1. 基于上述标记,我们知道ARRAY_INIT将始终生成一个数组。 因此,我们只需创build一个数组并填充它。 就歧义而言,词法分析阶段已经将ARRAY_INIT与对象属性访问器(例如obj[foo] )或string/正则expression式文本中的括号(例如“foo [] bar”或/ [] /)区分开来

  2. 这是微不足道的,但我们也有更多的令牌与new Array 。 而且,还不完全清楚,我们只是想创build一个数组。 我们看到“新”的标志,但“新”是什么? 然后,我们看到IDENTIFIER标记表示我们需要一个新的“Array”,但是JavaScript VM通常不会区分IDENTIFIER标记和“本地全局对象”的标记。 因此…

  3. 每次遇到一个IDENTIFIER标记时,我们都要查找范围链。 Javascript虚拟机为每个执行上下文包含一个“激活对象”,可以包含“参数”对象,本地定义的variables等。如果我们在激活对象中找不到它,我们开始查找范围链,直到到达全局范围。 如果没有发现,我们抛出一个ReferenceError

  4. 一旦findvariables声明,就调用构造函数。 new Array是一个隐含的函数调用,经验法则是在执行过程中函数调用较慢(为什么静态C / C ++编译器允许“函数内联” – SpiderMonkey等JS JIT引擎必须在运行中)

  5. Array构造函数被重载。 Array构造函数是作为本机代码实现的,所以它提供了一些性能增强,但是仍然需要检查参数长度并相应地采取行动。 而且,如果只提供一个参数,我们需要进一步检查参数的types。 new Array(“foo”)产生[“foo”],其中新的Array(1)产生[undefined]

所以为了简化这一切:使用数组文字,VM知道我们想要一个数组; 与new Array ,虚拟机需要使用额外的CPU周期来找出new Array 实际上做什么。

一个可能的原因是new Array需要在Array上进行名称查找(您可以在范围中使用该名称的variables),而[]不需要。

好问题。 第一个例子被称为数组文字。 在许多开发人员中创build数组是最好的方式。 性能差异可能是由检查新的Array()调用的参数,然后创build对象引起的,而文字直接创build一个数组。

性能相对较小的差异支持这一点,我认为。 顺便说一下,你可以用Object和object literal来做相同的testing。

这会有一定的意义

对象文字使我们能够编写支持许多特性的代码,但对于我们的代码的实现者来说,它仍然是相对简单的。 不需要直接调用构造函数或维护传递给函数的参数的正确顺序等。

http://www.dyn-web.com/tutorials/obj_lit.php