简体   繁体   English

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

[英]JavaScript Object Literal notation vs plain functions and performance implications?

Suppose I have functions like: 假设我有以下功能:

function foo() {

}

function bar() {

}

I can write above as Object Literal notation: 我可以在上面写为Object Literal表示法:

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

As far as I understand in the later case, an instance of Baz will be created when the script loads regardless if any Baz function is ever called. 据我所知,在后一种情况下,无论是否调用任何Baz函数,脚本加载时都会创建一个Baz实例。 In the former case, function object is only created when that function is called. 在前一种情况下,仅在调用该函数时才创建函数对象。 Am I correct about these assumptions? 我对这些假设是否正确?

If I am correct then the former would have higher performance (less memory) than the later in application where these functions are rarely called. 如果我是正确的那么前者将具有比后者在很少调用这些函数的应用程序中更高的性能(更少的内存)。 But the advantage of the later is that it gives greater modularity and lower global namespace pollution. 但后者的优势在于它提供了更大的模块化和更低的全局命名空间污染。

What is your take on this from your professional experience? 您从专业经验中对此有何看法? Is there a speed difference? 有速度差吗?

In the former case, function object is only created when that function is called. 在前一种情况下,仅在调用该函数时才创建函数对象。

No, the functions are created regardless. 不,无论如何都会创建这些功能。

Note that you can also do this: 请注意,您也可以这样做:

function foo() {
}

function bar() {
}

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

Or this: 或这个:

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

    function bar() {
    }

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

The primary purpose of putting the functions on Baz as properties is to make them available as "methods" on Baz . 将函数放在Baz作为属性的主要目的是使它们在Baz上作为“方法”使用。 This might be for convenience, for "namespacing", etc. In your first form (and my first form above), if that code is at global scope, foo and bar are added to the global scope, which can get pretty crowded pretty fast (esp. on browsers). 这可能是为了方便,“命名空间”等。在您的第一个表单(以及我上面的第一个表单)中,如果该代码位于全局范围,则foobar将添加到全局范围,这可能会非常快速地拥挤(尤其是在浏览器上)。 In your second example, the only global symbol is Baz because the functions are anonymous. 在第二个示例中,唯一的全局符号是Baz因为函数是匿名的。 In my final example above, the only global symbol is Baz but the functions aren't anonymous, they have names that debuggers and stack traces can show you (which is a good thing; more here ). 在上面的最后一个例子中,唯一的全局符号是Baz但函数不是匿名的,它们有调试器和堆栈跟踪可以显示的名称(这是一件好事; 更多信息 )。

In terms of trying to optimize when functions get created, here's how it works: When execution enters a given context (the global context, or the context related to calling a function), these things are done: 在尝试优化函数何时创建时,以下是它的工作原理:当执行进入给定的上下文 (全局上下文或与调用函数相关的上下文)时,这些事情就完成了:

  1. A behind-the-scenes execution context object is created. 创建幕后执行上下文对象。
  2. A behind-the-scenes variable object for that execution context is created. 创建该执行上下文的幕后变量对象
  3. In the case of a function context: 在函数上下文的情况下:
    1. A property is added to the variable object for arguments (the array-like thing you can use to access arguments) 将一个属性添加到arguments的变量对象中(可用于访问参数的类似数组的事物)
    2. A property is added to the variable object for each of the function's named arguments, with the value of the argument 对于每个函数的命名参数,将使用参数的值将属性添加到变量对象中
    3. If the function has a name, its name is added as a property of the variable object and has the value of the function object. 如果函数具有名称,则将其名称添加为变量对象的属性,并具有函数对象的值。
  4. Properties are created on the variable object for each variable declared with var in the execution context; 对于在执行上下文中用var声明的每个变量,在变量对象上创建属性; their values are initially undefined (regardless of whether the var has an initializer on it). 它们的值最初是undefined (无论var上是否有初始值设定项)。
  5. Every function declaration in the context is processed. 处理上下文中的每个函数声明 (Function expressions are not processed yet; more on the difference below.) A property on the variable object for each function name is created and receives the function object as its value. (函数表达式尚未处理;更多信息如下所示。)创建每个函数名的变量对象的属性,并接收函数对象作为其值。
  6. Step-by-step code execution begins. 逐步执行代码。
    • Like all expressions, function expressions are evaluated when they're encountered in the step-by-step flow. 与所有表达式一样,函数表达式在逐步流程中遇到时会被计算。
    • var statements that have initializers (eg, var a = 2; ) are treated exactly like assignment statements ( a = 2; ); 具有初始值设定项的var语句(例如, var a = 2; )与赋值语句( a = 2; )完全相同; the var aspect of it was done much earlier. 它的var方面早得多。 ( var is frequently misunderstood . For instance, we had this question just yesterday.) var 经常被误解 。例如,我们昨天才提出这个问题 。)

You'll note the difference above between function declarations and function expressions . 您将注意到函数声明和函数表达式之间的差异。 You can tell which is which by looking to see whether you're using the result as a right hand value — that is, are you assigning the result to a variable, using it as the right-hand side of a property definition in an object literal, or passing it into a function. 您可以通过查看是否将结果用作右手值来判断哪个是哪个 - 也就是说,您是将结果分配给变量,将其用作对象中属性定义的右侧文字,或将其传递给函数。 If you are, it's a function expression . 如果你是,那就是一个函数表达式 If you're not, it's a function declaration . 如果你不是,那就是一个功能声明

Function declaration example: 函数声明示例:

function foo() {
}

Function expression example: 函数表达式示例:

var foo = function() {
};

Another: 另一个:

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

(The foo line is a property declaration in an object literal that uses a function expression for the value.) foo行是对象文字中的属性声明,它使用函数表达式作为值。)

Named function expression example: 命名函数表达式示例:

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

Named function expressions should be valid, but they're poorly-supported by implementations in the wild (particularly IE) and so for now they must be avoided. 命名函数表达式应该是有效的,但它们在野外(特别是IE)中的实现很难得到支持,因此现在必须避免它们。 More here . 更多这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM