JavaScript Object Literal表示法与普通函数和性能影响?

时间:2011-04-22 10:32:01

标签: javascript

假设我有以下功能:

function foo() {

}

function bar() {

}

我可以在上面写为Object Literal表示法:

var Baz = {
  foo: function() {
  },
 bar: function() {
 }
};

据我所知,在后一种情况下,无论是否调用任何Baz函数,都会在脚本加载时创建Baz实例。在前一种情况下,仅在调用该函数时才创建函数对象。我对这些假设是否正确?

如果我是正确的,那么前者将比后来很少调用这些函数的应用程序具有更高的性能(更少的内存)。 但后者的优势在于它提供了更大的模块化和更低的全局命名空间污染。

根据您的专业经验,您对此有何看法? 有速度差异吗?

1 个答案:

答案 0 :(得分:43)

  

在前一种情况下,只有在调用该函数时才会创建函数对象。

不,无论如何都会创建这些功能。

请注意,您也可以这样做:

function foo() {
}

function bar() {
}

var Baz = {
  foo: foo,
  bar: bar
};

或者这个:

var Baz = (function() {
    function foo() {
    }

    function bar() {
    }

    return {
      foo: foo,
      bar: bar
    };
})();

Baz上的函数作为属性的主要目的是使它们在Baz上作为“方法”使用。这可能是为了方便,“命名空间”等。在您的第一个表单(以及我上面的第一个表单)中,如果该代码位于全局范围,则foobar将添加到全局范围,它可以非常快速地拥挤(特别是在浏览器上)。在第二个示例中,唯一的全局符号是Baz,因为函数是匿名的。在上面的最后一个例子中,唯一的全局符号是Baz,但函数不是匿名,它们具有调试器和堆栈跟踪可以显示给你的名称(这是一件好事; { {3}})。

在尝试优化函数创建时,以下是它的工作原理:当执行进入给定的上下文(全局上下文或与调用函数相关的上下文)时,这些东西是完成:

  1. 创建了一个幕后的执行上下文对象。
  2. 创建该执行上下文的幕后变量对象
  3. 在函数上下文的情况下:
    1. 将属性添加到arguments的变量对象中(可用于访问参数的类似数组的东西)
    2. 对于每个函数的命名参数,将一个属性添加到变量对象中,并使用参数的值
    3. 如果函数有名称,则其名称将作为变量对象的属性添加,并具有函数对象的值。
  4. 在执行上下文中使用var声明的每个变量在变量对象上创建属性;它们的值最初为undefined(无论var是否有初始值设定项。)
  5. 处理上下文中的每个函数声明。 (函数表达式尚未处理;更多内容如下。)创建每个函数名的变量对象的属性,并接收函数对象作为其值。
  6. 开始逐步执​​行代码。
    • 与所有表达式一样,函数表达式在逐步流程中遇到时会被计算。
    • 具有初始值设定项的
    • var语句(例如var a = 2;)与赋值语句(a = 2;)完全相同;它的var方面提前完成了。 (varmore here。例如,我们昨天才frequently misunderstood。)
  7. 你会注意到函数声明和函数表达式之间的区别。您可以通过查看是否将结果用作右手值来判断哪个是哪个 - 也就是说,您是将结果分配给变量,将其用作右侧对象文字中的属性定义,或将其传递给函数。如果你是,它是一个函数表达式。如果你不是,那就是一个函数声明

    功能声明示例:

    function foo() {
    }
    

    函数表达式示例:

    var foo = function() {
    };
    

    另:

    var Baz = {
        foo: function() { }
    };
    

    foo行是对象文字中的属性声明,它使用函数表达式作为值。)

    命名函数表达式示例:

    var f = function foo() {  // <== Don't do this (more below)
    };
    

    命名函数表达式应该是有效的,但它们在野外(特别是IE)中的实现很难得到支持,所以现在必须避免它们。 this question