JavaScript 对象文字符号与普通函数和性能影响?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5754538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript Object Literal notation vs plain functions and performance implications?
提问by ace
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. In the former case, function object is only created when that function is called. Am I correct about these assumptions?
据我了解,在后一种情况下,无论是否调用过任何 Baz 函数,都会在脚本加载时创建 Baz 实例。在前一种情况下,函数对象仅在调用该函数时创建。我对这些假设是否正确?
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?
根据您的专业经验,您对此有何看法?有速度差异吗?
回答by T.J. Crowder
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
. 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). In your second example, the only global symbol is Baz
because the functions are anonymous. In my final example above, the only global symbol is Baz
but the functions aren'tanonymous, they have names that debuggers and stack traces can show you (which is a good thing; more here).
将函数Baz
作为属性放置的主要目的是使它们可作为 上的“方法”使用Baz
。这可能是为了方便起见,为了“命名空间”等。在您的第一个表单(以及我上面的第一个表单)中,如果该代码在全局范围内,foo
并且bar
被添加到全局范围内,这会很快变得非常拥挤(尤其是. 在浏览器上)。在您的第二个示例中,唯一的全局符号是Baz
因为函数是匿名的。在我上面的最后一个示例中,唯一的全局符号是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:
在尝试优化何时创建函数方面,它是如何工作的:当执行进入给定的上下文(全局上下文,或与调用函数相关的上下文)时,完成以下操作:
- A behind-the-scenes execution contextobject is created.
- A behind-the-scenes variable objectfor that execution context is created.
- In the case of a function context:
- A property is added to the variable object for
arguments
(the array-like thing you can use to access arguments) - A property is added to the variable object for each of the function's named arguments, with the value of the argument
- 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.
- A property is added to the variable object for
- Properties are created on the variable object for each variable declared with
var
in the execution context; their values are initiallyundefined
(regardless of whether thevar
has an initializer on it). - Every function declarationin 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.
- 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 (e.g.,var a = 2;
) are treated exactly like assignment statements (a = 2;
); thevar
aspect of it was done much earlier. (var
is frequently misunderstood. For instance, we had this questionjust yesterday.)
- 创建了一个幕后执行上下文对象。
- 为该执行上下文创建了一个幕后变量对象。
- 在函数上下文的情况下:
- 一个属性被添加到变量对象中
arguments
(你可以用来访问参数的类似数组的东西) - 一个属性被添加到每个函数的命名参数的变量对象中,参数的值
- 如果函数有名字,它的名字被添加为变量对象的属性,并具有函数对象的值。
- 一个属性被添加到变量对象中
- 为
var
在执行上下文中声明的每个变量在变量对象上创建属性;它们的值是最初的undefined
(无论 上面是否var
有初始化程序)。 - 处理上下文中的每个函数声明。(函数表达式还没有被处理;更多关于下面的区别。)每个函数名称的变量对象的属性被创建并接收函数对象作为它的值。
- 分步代码执行开始。
You'll note the difference above between function declarationsand 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
行是对象字面量中的属性声明,它使用函数表达式作为值。)
Namedfunction 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. More here.
命名函数表达式应该是有效的,但它们在野外实现(特别是 IE)的支持很差,因此现在必须避免它们。更多在这里。