"whats the difference between function foo(){} and foo = function(){}?" 的意思是,“function foo(){}” 和 “foo = function(){}” 有什么区别?

19 浏览
0 Comments

"whats the difference between function foo(){} and foo = function(){}?" 的意思是,“function foo(){}” 和 “foo = function(){}” 有什么区别?

这个问题已经有答案了

可能重复:

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

它们相同吗?我一直在疑惑

admin 更改状态以发布 2023年5月21日
0
0 Comments

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

0
0 Comments

不,它们并不相同,尽管它们都会生成一个可以通过符号foo调用的函数。其中一个是函数声明,另一个是函数表达式。它们在不同的时间进行评估,在定义它们的范围上产生不同的影响,并且在不同的位置上是合法的。

引用我在另一个问题中的回答(为了相关性而进行了编辑),以防那个问题因某种原因被删除(并为了节省人们点击链接的时间):


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

更多信息请参见:Double takeNamed function expressions demystified

注意:下面的内容是在2011年撰写的。在2015年,函数声明在控制块中被添加到语言中,作为ES2015的一部分。它们的语义取决于你是否处于严格模式或松散模式,以及在松散模式下环境是否是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。对于表达式,这不是一个问题,因为它们是在控制流期间完成的。

由于语法无效,实现者可以自由选择执行何种操作。我从未遇到过我所期望的,即抛出语法错误并失败的语法解析器。相反,几乎所有的解析器都会忽略控制流语句,并根据在顶层有两个foo函数声明时应该做什么来处理(这在规范中是使用第二个函数;)。因此,只有第二个foo被使用。Firefox的SpiderMonkey是杰出的,它似乎将它们转换为表达式,因此其使用取决于x的值。Live example

0