它们是一样的吗?我一直想知道可能重复:
JavaScript: var functionName = function() {} vs function functionName() {}
答案 0 :(得分:31)
不,它们不一样,虽然它们都会产生一个可以通过符号foo
调用的功能。一个是函数声明,另一个是函数表达式。它们在不同的时间进行评估,对它们的定义范围产生不同的影响,并且在不同的地方是合法的。
在这里引用my answer to this other question(编辑了一点相关性),以防其他问题因某种原因被删除(以及保存链接后的人):
JavaScript有两个不同但相关的东西:函数声明和函数表达式。它们之间存在显着差异:
这是一个函数声明:
function foo() {
// ...
}
在执行任何分步代码之前,在进入封闭范围时评估函数声明。函数的名称(foo
)被添加到封闭范围(从技术上讲,变量对象用于执行上下文,函数定义在其中)。
这是一个函数表达式(具体来说,是一个匿名的,就像你引用的代码一样):
var foo = function() {
// ...
};
函数表达式作为逐步代码的一部分进行评估,在它们出现的位置(就像任何其他表达式一样)。那个创建一个没有名称的函数,它分配给foo
变量。
函数表达式也可以命名为而不是匿名。命名的一个看起来像这样:
var x = function foo() { // Valid, but don't do it; see details below
// ...
};
根据规范,命名函数表达式应有效。它应该创建一个名为foo
的函数,但不将foo
放入封闭范围,然后将该函数分配给x
变量(全部在逐步代码中遇到表达式时会发生这种情况。当我说它不应该将foo
放在封闭的范围内时,我的意思是:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
请注意,这与函数声明的工作方式有何不同(函数的名称 添加到封闭范围内)。
命名函数表达式适用于兼容的实现,但在野外实现中曾经存在多个错误,尤其是Internet Explorer 8及更早版本(以及Safari的早期版本)。 IE8处理命名函数expresssion 两次:首先作为函数声明(在进入执行上下文时),然后作为函数表达式 ,在过程中产生两个不同的功能。 (真)。
更多信息:Double take和此处:Named function expressions demystified
注意:以下是2011年编写的。2015年,控制块中的函数声明作为ECMAScript 2015的一部分添加到语言中。它们的语义因您是严格还是严格而有所不同松散模式,如果环境是Web浏览器,则处于松散模式。当然,关于您使用的环境是否正确支持ES2015的定义。 (令我惊讶的是,在2017年7月的撰写中,Babel也没有正确地将它们转换为。)因此,在特定情况下,你只能在控制流结构中可靠地使用函数声明,所以它仍然可能现在,最好使用函数表达式。
最后,他们之间的另一个区别是他们是合法的。函数表达式可以出现在表达式可以出现的任何地方(几乎在任何地方)。函数声明只能出现在其封闭范围的顶层,在任何控制流语句之外。例如,这是有效的:
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
函数1}}来评估。这对表达式来说不是问题,因为它们是在控制流程中完成的。
由于语法无效,实现可以自由地执行他们想要的操作。我从来没有遇到过一个能达到预期效果的,就是抛出语法错误而失败。相反,几乎所有这些都忽略了控制流语句,并且如果在顶层有两个 foo
函数声明(使用第二个;在规范中),它们应该做什么。所以只使用第二个foo
。 Firefox的SpiderMonkey是杰出的,它似乎(有效地)将它们转换为表达式,因此它使用取决于x
的值。 Live example。
答案 1 :(得分:1)
我在提出非常相似的问题时得到了很好的解释:Two functions with the same name in JavaScript - how can this work?