关于javascript:function foo()和foo=function()有什么区别?

whats the difference between function foo(){} and foo = function(){}?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}

它们是一样的吗?我一直在想


不,它们是不同的,尽管它们都会导致一个可以通过符号foo调用的函数。一个是函数声明,另一个是函数表达式。它们在不同的时间进行评估,对定义它们的范围有不同的影响,并且在不同的地方是合法的。好的。

在这里引用我对另一个问题的回答(为了相关性编辑了一点),以防出于某种原因删除了另一个问题(并保存链接后面的人):好的。

JavaScript有两个不同但相关的东西:函数声明和函数表达式。它们之间有明显的区别:好的。

这是一个函数声明:好的。

1
2
3
function foo() {
    // ...
}

在执行任何分步代码之前,在进入封闭范围时对函数声明进行评估。函数名(foo添加到封闭范围中(从技术上讲,是函数定义的执行上下文的变量对象)。好的。

这是一个函数表达式(特别是匿名表达式,如引用的代码):好的。

1
2
3
var foo = function() {
    // ...
};

函数表达式的计算是逐步代码的一部分,在它们出现的地方(就像任何其他表达式一样)。它创建了一个没有名称的函数,并将其分配给foo变量。好的。

函数表达式也可以命名,而不是匿名。一个命名的类似于:好的。

1
2
3
var x = function foo() {  // Valid, but don't do it; see details below
    // ...
};

根据规范,命名函数表达式应该是有效的。它应该创建一个名为foo的函数,但不应将foo放在封闭范围内,然后将该函数赋给x变量(所有这些都是在逐步代码中遇到表达式时发生的)。当我说不应该把foo放在封闭的范围内时,我的意思是:好的。

1
2
3
4
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处理命名函数表达式两次:首先作为函数声明(在进入执行上下文时),然后作为函数表达式,在进程中生成两个不同的函数。(真的。)好的。

这里的更多信息:double take和here:已命名函数表达式已解除定义好的。

注:以下为2011年编写。2015年,控制块中的函数声明作为ECMAScript 2015的一部分添加到语言中。它们的语义取决于您是处于严格模式还是松散模式,如果环境是Web浏览器,它们的语义也取决于松散模式。当然,关于您所使用的环境是否对ES2015定义有正确的支持。(令我惊讶的是,截至2017年7月的这篇文章,Babel也没有正确地表达出来。)因此,在特定的情况下,您只能在控制流结构中可靠地使用函数声明,因此现在使用函数表达式可能还是最好的。好的。

最后,它们之间的另一个区别是它们在哪里是合法的。函数表达式可以出现在表达式可以出现的任何位置(实际上是任何位置)。函数声明只能出现在其封闭范围的顶层,在任何控制流语句之外。例如,这是有效的:好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function bar(x) {
    var foo;

    if (x) {
        foo = function() {  // Function expression...
            // Do X
        };
    }
    else {
        foo = function() {  // ...and therefore legal
            // Do Y
        };
    }
    foo();
}

…但这不是,也不像在大多数实现中那样:好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function bar(x) {

    if (x) {
        function foo() {  // Function declaration -- INVALID
            // Do X
        }
    }
    else {
        function foo() {  // INVALID
            // Do Y
        }
    }
    foo();
}

这是完全有道理的:由于foo函数声明是在进入bar函数时进行评估的,所以在执行任何分步代码之前,解释器不知道要评估哪个foo。对于表达式来说,这不是问题,因为它们是在控制流期间完成的。好的。

由于语法无效,实现可以自由地执行它们想要的操作。我从来没有遇到过一个能达到我预期的效果,那就是抛出语法错误而失败。相反,几乎所有的声明都忽略了控制流语句,如果在顶层有两个foo函数声明(即使用第二个声明;这在规范中),则执行它们应该执行的操作。所以只使用第二个foo。火狐的蜘蛛猴是最突出的,它似乎(有效地)把它们转换成表达式,所以它使用的表达式取决于x的值。活生生的例子。好的。好啊。


我得到了一个很好的解释,同时问了一个非常相似的问题:在javascript中有两个同名的函数-这是如何工作的?