为什么 arr = [] 比 arr = new Array 快? [英] Why is arr = [] faster than arr = new Array?

查看:32
本文介绍了为什么 arr = [] 比 arr = new Array 快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行了这段代码并得到了以下结果.我很想知道为什么 [] 更快?

I ran this code and got the below result. I curious to know why [] is faster?

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:363 毫秒
    • using []: 299ms
    • using new: 363ms
    • 感谢 Raynos 这里有一个 此代码的基准 以及定义变量的更多可能方法.

      Thanks to Raynos here is a benchmark of this code and some more possible way to define a variable.

      推荐答案

      进一步扩展以前的答案...

      Further expanding on previous answers...

      从一般编译器的角度来看,不考虑特定于 VM 的优化:

      From a general compilers perspective and disregarding VM-specific optimizations:

      首先,我们通过词法分析阶段对代码进行标记.

      First, we go through the lexical analysis phase where we tokenize the code.

      举例来说,可能会产生以下令牌:

      By way of example, the following tokens may be produced:

      []: 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)
      

      希望这能为您提供足够的可视化,以便您了解需要多少(或更少)处理.

      Hopefully this should provide you a sufficient visualization so you can understand how much more (or less) processing is required.

      1. 基于上述标记,我们知道 ARRAY_INIT 将始终生成一个数组.因此,我们只需创建一个数组并填充它.就歧义而言,词法分析阶段已经将 ARRAY_INIT 与对象属性访问器(例如 obj[foo])或字符串/正则表达式中的括号(例如foo[]bar"或/[]/)

      1. Based on the above tokens, we know as a fact ARRAY_INIT will always produce an array. We therefore simply create an array and populate it. As far as ambiguity, the lexical analysis stage has already distinguished ARRAY_INIT from an object property accessor (e.g. obj[foo]) or brackets inside strings/regex literals (e.g. "foo[]bar" or /[]/)

      这是微不足道的,但我们也有更多的带有 new Array 的标记.此外,目前还不完全清楚我们只是想创建一个数组.我们看到了new"令牌,但是new"是什么?然后我们会看到 IDENTIFIER 令牌,它表示我们想要一个新的数组",但 JavaScript VM 通常不区分 IDENTIFIER 令牌和本地全局对象"的令牌.因此...

      This is miniscule, but we also have more tokens with new Array. Furthermore, it's not entirely clear yet that we simply want to create an array. We see the "new" token, but "new" what? We then see the IDENTIFIER token which signifies we want a new "Array," but JavaScript VM's generally do not distinguish an IDENTIFIER token and tokens for "native global objects." Therefore...

      每次遇到 IDENTIFIER 令牌时,我们都必须查找作用域链.Javascript VM 为每个执行上下文包含一个激活对象",其中可能包含参数"对象、本地定义的变量等.如果我们在 Activation 对象中找不到它,我们开始查找作用域链,直到到达全局作用域.如果什么也没找到,我们就会抛出一个 ReferenceError.

      We have to look up the scope chain each time we encounter an IDENTIFIER token. Javascript VMs contain an "Activation object" for each execution context which may contain the "arguments" object, locally defined variables, etc. If we cannot find it in the Activation object, we begin looking up the scope chain until we reach the global scope. If nothing is found, we throw a ReferenceError.

      一旦我们找到了变量声明,我们就调用构造函数.new Array 是一个隐式的函数调用,经验法则是函数调用在执行过程中会变慢(因此静态 C/C++ 编译器允许函数内联"——这是 SpiderMonkey 等 JS JIT 引擎所拥有的即时执行)

      Once we've located the variable declaration, we invoke the constructor. new Array is an implicit function call, and the rule of thumb is that function calls are slower during execution (hence why static C/C++ compilers allow "function inlining" - which JS JIT engines such as SpiderMonkey have to do on-the-fly)

      Array 构造函数被重载.Array 构造函数是作为本机代码实现的,因此它提供了一些性能增强,但它仍然需要检查参数长度并采取相应的行动.此外,如果只提供了一个参数,我们需要进一步检查参数的类型.new Array("foo") 产生 ["foo"] 而 new Array(1) 产生 [undefined]

      The Array constructor is overloaded. The Array constructor is implemented as native code so it provides some performance enhancements, but it still needs to check for arguments length and act accordingly. Moreover, in the event only one argument is supplied, we need to further check the type of the argument. new Array("foo") produces ["foo"] where as new Array(1) produces [undefined]

      所以为了简化这一切:使用数组字面量,VM 知道我们需要一个数组;使用 new Array,VM 需要使用额外的 CPU 周期来确定 new Array 实际上做了什么.

      So to simplify it all: with array literals, the VM knows we want an array; with new Array, the VM needs to use extra CPU cycles to figure out what new Array actually does.

      这篇关于为什么 arr = [] 比 arr = new Array 快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆