JavaScript中的{}与new Object()性能比较

29

我想了解为什么在执行相同操作时会有性能差异?

图片描述

基准测试


6
通常情况下,我认为直接调用函数会比使用构造函数更快。 - iMom0
根据这个回答,基本上new Object(){}多做了一些事情。 - Ja͢ck
2
这个答案更为接近:https://dev59.com/tW445IYBdhLWcg3w_PG3#15030757 - Salman A
@Jack,我在那里看不到任何与性能相关的帖子。你说的“少数其他事情”甚至也没有。 - Deepak Ingole
2
为什么arr = []比arr = new Array快?密切相关。 - Praveen
显示剩余11条评论
1个回答

35

性能可以用 {} 这个对象字面量来解释:

  1. 在 JavaScript 中,{} 是一种对象字面量,而字面量的计算速度更快。
  2. 此外,字面量在代码中占用的空间更少,因此文件大小更小。
  3. 使用对象字面量和 new Object() 代码的最终结果相同,但在几乎所有浏览器中执行速度更快(Firefox 3.5 几乎没有区别)。
  4. 随着对象属性和数组项的数量增加,使用字面量的好处也越来越多。

JavaScript 中的作用域管理机制使对象字面量 {} 的执行速度更快

当 JavaScript 代码被执行时,会创建一个执行上下文。执行上下文(有时也称为作用域)定义了代码要在其中执行的环境。

在页面加载时创建全局执行上下文,并在函数执行时创建其他执行上下文,最终创建一个执行上下文堆栈,其中顶部的上下文是活动的上下文。

每个执行上下文都有一个与之关联的作用域链,用于标识符解析。作用域链包含一个或多个变量对象,这些对象为执行上下文中的标识符定义了作用域范围。

全局执行上下文的作用域链中只有一个变量对象,该对象定义了 JavaScript 中所有全局变量和函数。

当创建函数(但未执行时),其内部的 [[Scope]] 属性被赋值为它所创建的执行上下文的作用域链(无法通过 JavaScript 访问内部属性,因此无法直接访问此属性)。

稍后,当执行流进入函数时,将创建一个激活对象,并使用 this、arguments、命名参数和任何局部于函数的变量进行初始化。激活对象首先出现在执行上下文的作用域链中,然后是函数的 [[Scope]] 属性中包含的对象。

在代码执行期间,通过搜索执行上下文的作用域链来解析诸如变量和函数名称之类的标识符。

标识符解析从作用域链的前面开始,向后进行。考虑以下代码:

function Add(n1, n2) {
  this.n1 = n1;
  this.n2 = n2;
  this.val = this.n1 + this.n2;
}

var result = new Add(5, 10);
当执行此代码时,add函数有一个[[Scope]]属性,其中仅包含全局变量对象。
当代码执行到add函数时,会创建一个新的执行上下文,并将包含this、arguments、n1和n2的激活对象放入作用域链中。
下图“执行上下文和作用域链的关系”说明了在执行add函数时发生的幕后对象关系。 enter image description here 在add函数内部,需要在函数执行时解析标识符num1和num2。
这种解析是通过检查作用域链中的每个对象直到找到特定的标识符来执行的。
搜索始于作用域链中的第一个对象,即包含函数本地变量的激活对象。
如果在那里找不到标识符,则检查作用域链中的下一个对象。当找到标识符时,搜索停止。
在这个示例中,标识符num1和num2存在于本地激活对象中,因此搜索永远不会转向全局对象。
理解JavaScript中的作用域和作用域链管理很重要,因为标识符解析性能直接与作用域链中要搜索的对象数量相关。
标识符在作用域链中存在得越高,搜索时间就越长,访问该变量所需的时间也越长;如果没有正确管理作用域,它们可能会对脚本的执行时间产生负面影响。

3
飞行员,请在“性能”标题下找到我的更新。 - Mazzu
{} 是字面量,在 JavaScript 中字面量的计算速度更快,但 new Object() 是对函数 Object() 的构造函数调用,该函数具有自己的定义,需要相对更长的时间来计算。 - Mazzu
在JavaScript中,通过{}创建对象时,我们实际上是在声明它。除了函数之外,声明会被优先处理。 - Mazzu
当你抄袭别人的原话时,请注明出处。 - megawac
3
这个回答中提出了一个非常好的观点:https://dev59.com/tW445IYBdhLWcg3w_PG3 -- 总结一下,你可以设置一个函数来从字面上创建实例或构造函数。使用字面量符号创建实例时,每个实例都包含所有方法,而使用构造函数时,所有实例都引用原型方法。也就是说,当创建许多实例时,构造函数具有更好的内存性能。 - Federico
显示剩余11条评论

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