我们有两种不同的方式在 JavaScript 中进行函数表达式:
命名函数表达式 (NFE):
var boo = function boo () {
alert(1);
};
匿名函数表达式:
var boo = function () {
alert(1);
};
并且它们都可以通过 boo();
调用。我真的不明白为什么/何时应该使用匿名函数以及何时应该使用命名函数表达式。他们之间有什么区别?
最佳答案
对于匿名函数表达式,该函数是匿名——字面意思是,它没有名称。您分配给它的变量有名称,但函数没有。 (更新:ES5 中确实如此。从 ES2015 [又名 ES6] 开始,使用匿名表达式创建的函数通常会获得真实名称 [但不是自动标识符],请继续阅读...)
名字很有用。名称可以在堆栈跟踪、调用堆栈、断点列表等中看到。名称是一件好事™。
(您过去必须小心旧版本 IE [IE8 及以下] 中的命名函数表达式,因为它们在两个完全不同的时间错误地创建了两个完全独立的函数对象 [更多内容请参阅我的博客文章 Double take ]。如果您需要支持 IE8 [!!],最好坚持使用匿名函数表达式或函数声明,但避免使用命名函数表达式。)
关于命名函数表达式的一个关键点是,它为函数体内的函数创建一个具有该名称的范围内标识符:
var x = function example() {
console.log(typeof example); // "function"
};
x();
console.log(typeof example); // "undefined"
然而,从 ES2015 开始,许多“匿名”函数表达式创建带有名称的函数,而这早于各种现代 JavaScript 引擎在从上下文推断名称方面非常聪明。在 ES2015 中,匿名函数表达式会生成名为 boo
的函数。然而,即使使用 ES2015+ 语义,也不会创建自动标识符:
var obj = {
x: function() {
console.log(typeof x); // "undefined"
console.log(obj.x.name); // "x"
},
y: function y() {
console.log(typeof y); // "function"
console.log(obj.y.name); // "y"
}
};
obj.x();
obj.y();
函数名称的分配是通过 SetFunctionName 完成的规范中各种操作中使用的抽象操作。
简短的版本基本上是指任何时候匿名函数表达式出现在赋值或初始化等内容的右侧,例如:
var boo = function() { /*...*/ };
(或者可以是 let
或 const
而不是 var
),或者
var obj = {
boo: function() { /*...*/ }
};
或
doSomething({
boo: function() { /*...*/ }
});
(最后两个实际上是同一件事),生成的函数将有一个名称(示例中为 boo
)。
有一个重要且有意的异常(exception):分配给现有对象的属性:
obj.boo = function() { /*...*/ }; // <== Does not get a name
这是因为新功能添加过程中出现信息泄露问题;详细信息在我对另一个问题的回答 here .
关于javascript - 为什么使用命名函数表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33745751/