什么决定JavaScript函数是命名匿名函数还是常规函数?

什么决定JavaScript函数是命名匿名函数还是常规函数?,javascript,syntax,semantics,Javascript,Syntax,Semantics,阅读时,我注意到函数的一些有趣之处: 如上所述,提供给匿名函数的名称仅(或至少应该)对该函数自己的作用域可用 在nodejs提示符下根据教程中的代码输入一些内容,我能够验证node是否同意作者的观点: function add(foo, bar) { return foo + bar; } add(1, 2); 给我3个,然后: var five = (function plus(foo, bar) { return foo + bar;

阅读时,我注意到函数的一些有趣之处:

如上所述,提供给匿名函数的名称仅(或至少应该)对该函数自己的作用域可用

在nodejs提示符下根据教程中的代码输入一些内容,我能够验证node是否同意作者的观点:

function add(foo, bar) {
  return foo + bar;
}

add(1, 2);
给我3个,然后:

var five = (function plus(foo, bar) {
             return foo + bar;
           })(2, 3);
plus(2, 3);
获取有关未定义加号的语法错误


我有点困惑,因为我用来定义这两个函数的代码是相同的(除了名称)。JavaScript如何知道第一个是常规函数,第二个是命名匿名函数?

第一个是普通函数声明。声明的名称被引入当前范围,并隐式引用函数体。在这种形式中,
函数
是一条语句,因此不返回任何值


第二个是函数表达式,解释器知道这一点,因为它是赋值右边的一部分,并且因为它周围有大括号。任何时候,如果可能提供了其他“值”(或“表达式”),则出现“函数”一词,那么您得到的就是函数表达式。该表达式的结果是对函数体的引用

函数表达式的名称(如果给定)仅在函数中可用,如链接中所述

我认为该链接中的命名法不正确。在我看来,他们所谓的“命名匿名函数”应该被称为“命名函数表达式”。这个明显的错误可能源于以下事实:所有匿名函数实际上都是函数表达式,但并非所有函数表达式都是匿名的

请注意,如果使用此样式:

var foo = function bar() {
    ...
}
然后如上所述,bar是一个函数表达式,其结果随后分配给变量
foo
。名称
不在当前范围内,但在函数本身中可用

变量
foo
的声明将被提升到作用域的顶部,但在实际执行上述行之前,不会被赋予其值(即对函数表达式的引用)

另一个有趣的差异演示是(从Chrome控制台):


请注意,唯一的区别是后者中有一个分配给
a
。尝试使用语句声明匿名函数是非法的,因为语言语法要求函数语句包含函数的标签。但是后者隐式地是一个函数表达式,允许匿名。

“命名匿名”:)它不能同时是两个。@pimvdb确实如此。它实际上是一个命名函数表达式,不是匿名函数。@pimvdb:LOL,我知道,对吗?但这就是文章所说的。“我想你不知道ECMA怎么称呼它们吗?”塞缪尔·埃德温·沃德:我相信这是一个函数声明,而不是一个函数表达式。问题是只有函数表达式可以是匿名的。事实上,这种情况经常发生,很明显,它们(错误地)已经成为同义词。我已经对这个答案投了更高的票,因为它表明了我对手头的主题有着清晰的认识,并且在解释这个问题上有着不寻常的技巧。我也同意“命名匿名函数”这个短语是一个矛盾修饰法。将“命名函数表达式”的值赋给另一个名称的变量的示例非常好地解释了这里发生的事情。但我仍然对为什么(或者如何)感到困惑。[继续]“因为它是作业右侧的一部分,而且因为它周围有大括号。”我猜大括号是指ASCII 40和41?你的解释是否必要和充分?你能举出章节吗?如果我在函数调用中提供相关代码作为参数,不带括号,也不将其分配给变量,那么它是函数声明还是命名函数表达式?@SamuelEdwinWard这也是函数表达式。一般来说,只有语法
function foo(){…}
是正常的函数声明,提示是
function
标记,是语句中的第一件事。几乎所有其他东西都是函数表达式。我认为所有匿名函数实际上都是函数表达式,但并不是所有函数表达式都是匿名的,这是矛盾修饰法的一部分。@SamuelEdwinWard最终归结为语言语法。函数声明完全按照它所说的做,不再做更多的事情。它将变量引入范围。但任何时候,当您在需要值(即表达式)的位置键入单词
function
时,它都会隐式地成为一个函数表达式。由于
()
的内容必须是表达式,因此其中的任何函数都是函数表达式。@SamuelEdwinWard我想您可能正在查找以下内容:
> function() { }
SyntaxError: Unexpected token (
> a = function() { }
function () { }