为了账号安全,请及时绑定邮箱和手机立即绑定

为什么使用命名函数表达式?

为什么使用命名函数表达式?

MM们 2019-06-18 12:57:16
为什么使用命名函数表达式?在JavaScript中进行函数表达式有两种不同的方法:命名函数表达式:var boo = function boo () {   alert(1);};匿名函数表达式:var boo = function () {   alert(1);};它们都可以用boo();..我真的不明白为什么/什么时候应该使用匿名函数,什么时候应该使用命名函数表达式。他们之间有什么区别?
查看完整描述

3 回答

?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

对于匿名函数表达式,函数是匿名-字面上说,它没有名字。要分配给它的变量有一个名称,但是函数没有。(更新:在ES5中是这样的。截至ES 2015[又名ES6],使用匿名表达式创建的函数通常会获得真名[但不是自动标识符],然后继续读取.)


名字很有用。名称可以在堆栈跟踪、调用堆栈、断点列表等中看到。名称是一件好事,™。


(过去,您必须小心使用早期版本的IE[IE8及以下版本]中的命名函数表达式,因为它们在两个完全不同的时间错误地创建了两个完全独立的函数对象(更多在我的博客文章中)。双取]。如果您需要支持IE8[!],最好还是使用匿名函数表达式或函数声明,但避免使用命名函数表达式。)


命名函数表达式的一个关键之处是,它为函数体中的函数创建一个具有该名称的作用域内标识符:


var x = function example() {

    console.log(typeof example); // "function"

};

x();

console.log(typeof example);     // "undefined"

然而,到ES 2015时,许多“匿名”函数表达式创建了带有名称的函数,而各种现代JavaScript引擎在从上下文中推断名称方面相当聪明,这早于此。在ES 2015中,匿名函数表达式将生成一个名为boo..但是,即使使用ES 2015+语义,也不会创建自动标识符:


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() { /*...*/ };

(或者可能是letconst而不是var),或

var obj = {
    boo: function() { /*...*/ }};

doSomething({
    boo: function() { /*...*/ }});

(最后那两件事真的是一样的),则生成的函数将有一个名称(boo,在例子中)。

有一个重要的、有意为之的例外:为现有对象上的属性分配:

obj.boo = function() { /*...*/ }; // <== Does not get a name

这是因为在添加新功能的过程中,出现了信息泄漏问题;我在回答另一个问题时详细说明了这一问题。这里.


查看完整回答
反对 回复 2019-06-18
?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

如果需要引用自己(例如,递归调用),命名函数是有用的。实际上,如果要将文字函数表达式作为参数直接传递给另一个函数,则该函数表达式。不可能除非命名为ES5严格模式,否则直接引用它自己。

例如,考虑以下代码:

setTimeout(function sayMoo() {
    alert('MOO');
    setTimeout(sayMoo, 1000);}, 1000);

如果函数表达式传递给setTimeout是匿名的;我们需要将它赋值给一个变量,而不是在setTimeout打电话。这种方式,用一个命名的函数表达式,稍微短一些,更整洁。

历史上,即使使用匿名函数表达式,也可以编写这样的代码,方法是利用arguments.callee...

setTimeout(function () {
    alert('MOO');
    setTimeout(arguments.callee, 1000);}, 1000);

..但arguments.callee被废弃,并且在ES5严格模式下被彻底禁止。因此,MDN建议:

避免使用arguments.callee()任一种为函数表达式指定名称或者使用函数声明,其中函数必须调用自己。

(强调地雷)


查看完整回答
反对 回复 2019-06-18
  • 3 回答
  • 0 关注
  • 507 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信