javascript 函数 foo(){} 和 foo = function(){} 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5403121/
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
whats the difference between function foo(){} and foo = function(){}?
提问by Tyler Gillies
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
可能的重复:
JavaScript:var functionName = function() {} vs function functionName() {}
are they the same? I've always wondered
他们是一样的吗?我一直想知道
回答by T.J. Crowder
No, they're not the same, although they do both result in a function you can call via the symbol foo
. One is a function declaration, the other is a function expression. They are evaluated at different times, have different effects on the scope in which they're defined, and are legal in different places.
不,它们不一样,尽管它们都产生了一个可以通过符号调用的函数foo
。一个是函数声明,另一个是函数表达式。它们在不同的时间被评估,对它们定义的范围有不同的影响,并且在不同的地方是合法的。
Quoting my answer to this other questionhere (edited a bit for relevance), in case the other question were ever removed for some reason (and to save people following the link):
在这里引用我对另一个问题的回答(为相关性做了一些编辑),以防其他问题因某种原因被删除(并保存人们点击链接):
JavaScript has two different but related things: Function declarations, and function expressions. There are marked differences between them:
JavaScript 有两个不同但相关的东西:函数声明和函数表达式。它们之间存在显着差异:
This is a function declaration:
这是一个函数声明:
function foo() {
// ...
}
Function declarations are evaluated upon entry into the enclosing scope, before any step-by-step code is executed. The function's name (foo
) is added to the enclosing scope (technically, the variable objectfor the execution contextthe function is defined in).
在执行任何分步代码之前,函数声明在进入封闭范围时进行评估。函数的名称 ( foo
) 被添加到封闭范围(从技术上讲,函数在其中定义的执行上下文的变量对象)。
This is a function expression(specifically, an anonymous one, like your quoted code):
这是一个函数表达式(特别是一个匿名的,就像你引用的代码一样):
var foo = function() {
// ...
};
Function expressions are evaluated as part of the step-by-step code, at the point where they appear (just like any other expression). That one creates a function with no name, which it assigns to the foo
variable.
函数表达式作为分步代码的一部分在它们出现的地方进行评估(就像任何其他表达式一样)。该函数创建了一个没有名称的函数,并将其分配给foo
变量。
Function expressions can also be namedrather than anonymous. A named one looks like this:
函数表达式也可以命名而不是匿名。一个命名的看起来像这样:
var x = function foo() { // Valid, but don't do it; see details below
// ...
};
A named function expression shouldbe valid, according to the spec. It should create a function with the name foo
, but notput foo
in the enclosing scope, and then assign that function to the x
variable (all of this happening when the expression is encountered in the step-by-step code). When I say it shouldn't put foo
in the enclosing scope, I mean exactly that:
根据规范,命名函数表达式应该是有效的。它应该创建一个名为 的函数foo
,但不要放在foo
封闭范围内,然后将该函数分配给x
变量(所有这些都发生在分步代码中遇到表达式时)。当我说它不应该放在foo
封闭范围内时,我的意思是:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
Note how that's different from the way function declarationswork (where the function's name isadded to the enclosing scope).
请注意如何将是一个从单向函数的不同声明的工作(如该函数的名称被添加到封闭范围)。
Named function expressions work on compliant implementations, but there used to be several bugs in implementations in the wild, most especially Internet Explorer 8 and earlier (and some early versions of Safari). IE8 processes a named function expresssion twice: First as a function declaration(upon entry into the execution context), and then later as a function expression, generating two distinct functions in the process. (Really.)
命名函数表达式适用于兼容的实现,但在野外实现中曾经存在一些错误,尤其是 Internet Explorer 8 及更早版本(以及一些早期版本的 Safari)。IE8 处理命名函数表达式两次:首先作为函数声明(进入执行上下文时),然后作为函数表达式,在该过程中生成两个不同的函数。(真的。)
More here: Double takeand here: Named function expressions demystified
更多信息:Double take和这里:命名函数表达式揭秘
NOTE:The below was written in 2011. In 2015, function declarations in control blocks were added to the language as part of ECMAScript 2015. Their semantics vary depending on whether you're in strict or loose mode, and in loose mode if the environment is a web browser. And of course, on whether the environment you're using has correct support for the ES2015 definition for them. (To my surprise, as of this writing in July 2017, Babeldoesn't correctly transpile them, either.) Consequently, you can only reliably use function declarations within control-flow structures in specific situations, so it's still probably best, for now, to use function expressions instead.
注意:以下内容写于 2011 年。2015 年,控制块中的函数声明作为 ECMAScript 2015 的一部分添加到语言中。它们的语义因您处于严格模式还是松散模式而有所不同,如果环境处于松散模式是一个网络浏览器。当然,关于您使用的环境是否正确支持 ES2015 定义。(令我惊讶的是,截至 2017 年 7 月撰写本文时,Babel也没有正确转译它们。)因此,您只能在特定情况下可靠地在控制流结构中使用函数声明,因此目前它仍然可能是最好的, 改为使用函数表达式。
And finally, another difference between them is where they're legal. A function expression can appear anywhere an expression can appear (which is virtually anywhere). A function declarationcan only appear at the top level of its enclosing scope, outside of any control-flow statements. So for instance, this is valid:
最后,它们之间的另一个区别是它们的合法性。函数表达式可以出现在表达式可以出现的任何地方(实际上是任何地方)。函数声明只能出现在其封闭范围的顶层,在任何控制流语句之外。例如,这是有效的:
function bar(x) {
var foo;
if (x) {
foo = function() { // Function expression...
// Do X
};
}
else {
foo = function() { // ...and therefore legal
// Do Y
};
}
foo();
}
...but this is not, and does notdo what it looks like it does on most implementations:
function bar(x) {
if (x) {
function foo() { // Function declaration -- INVALID
// Do X
}
}
else {
function foo() { // INVALID
// Do Y
}
}
foo();
}
And it makes perfect sense: Since the foo
function declarations are evaluated upon entry into the bar
function, before any step-by-step code is executed, the interpreter has no idea which foo
to evaluate. This isn't a problem for expressions since they're done during the control-flow.
function bar(x) {
var foo;
if (x) {
foo = function() { // Function expression...
// Do X
};
}
else {
foo = function() { // ...and therefore legal
// Do Y
};
}
foo();
}
...但这不是,并且不会像在大多数实现中那样做:
function bar(x) {
if (x) {
function foo() { // Function declaration -- INVALID
// Do X
}
}
else {
function foo() { // INVALID
// Do Y
}
}
foo();
}
这完全有道理:由于foo
函数声明在进入函数时被评估bar
,在执行任何一步一步的代码之前,解释器不知道foo
要评估哪个。这对表达式来说不是问题,因为它们是在控制流期间完成的。
Since the syntax is invalid, implementations are free to do what they want. I've never met one that did what I would have expected, which is to throw a syntax error and fail. Instead, nearly all of them just ignore the control flow statements and do what they should do if there are two foo
function declarations at the top level (which is use the second one; that's in the spec). So only the second foo
is used. Firefox's SpiderMonkey is the standout, it seems to (effectively) convert them into expressions, and so which it uses depends on the value of x
. Live example.
由于语法无效,实现可以自由地做他们想做的事。我从未遇到过按照我的预期执行的操作,即抛出语法错误并失败。相反,几乎所有这些都只是忽略控制流语句,并foo
在顶层有两个函数声明时做他们应该做的事情(使用第二个;这是在规范中)。所以只使用第二个foo
。Firefox 的 SpiderMonkey 是最出色的,它似乎(有效地)将它们转换为表达式,因此它使用的内容取决于x
. 活生生的例子。
回答by tillda
I got an excellent explanation on this while asking very similar question: Two functions with the same name in JavaScript - how can this work?
我在问非常相似的问题时得到了一个很好的解释:JavaScript 中的两个同名函数 - 这怎么工作?