4

在阅读“A re-introduction to JavaScript”时,我注意到函数的一些有趣之处:

如上所述提供给匿名函数的名称(或至少应该)仅可用于函数自己的范围。

在 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);

给我一个关于 plus 未定义的语法错误。

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

4

1 回答 1

7

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

第二个是函数表达式,解释器知道这一点,因为它是赋值右侧的一部分,并且因为它周围有大括号。每当单词function出现在可以提供其他“值”(或“表达式”)的地方,那么你所拥有的就是一个函数表达式。该表达式的结果是对函数体的引用。

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

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

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

var foo = function bar() {
    ...
}

then 如上所述bar是一个函数表达式,然后将其结果分配给变量foo。该名称bar未放入当前范围,但在函数本身中可用。

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

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

> function() { }
SyntaxError: Unexpected token (
> a = function() { }
function () { }

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

于 2012-08-22T20:43:28.463 回答