它不起作用,因为它被解析为函数声明
,并且函数声明的名称标识符是必需的。
当它用括号括起来时,它被计算为 FunctionExpression
,函数表达式可以命名或不命名。
的语法如下所示:FunctionDeclaration
function Identifier ( FormalParameterListopt ) { FunctionBody }
和 s:FunctionExpression
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
如您所见,(标识符选择)标记是可选的,因此我们可以有一个不定义名称的函数表达式:Identifier
FunctionExpression
(function () {
alert(2 + 2);
}());
或命名函数表达式:
(function foo() {
alert(2 + 2);
}());
括号(正式称为分组运算符)只能将表达式括起来,并计算函数表达式。
这两种语法作品可能模棱两可,并且它们看起来可能完全相同,例如:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
解析器知道它是 a 还是 a,这取决于它出现的上下文。FunctionDeclaration
FunctionExpression
在上面的示例中,第二个是表达式,因为逗号运算符也可以只处理表达式。
另一方面,s 实际上只能出现在所谓的“”代码中,这意味着代码在全局范围之外,以及其他函数内部。FunctionDeclaration
Program
FunctionBody
应避免使用块内的函数,因为它们可能导致不可预测的行为,例如:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
上面的代码实际上应该生成一个 ,因为 Block
只能包含语句(并且 ECMAScript 规范没有定义任何函数语句),但大多数实现都是容许的,并且会简单地采用第二个函数,即发出警报的函数。SyntaxError
'false!'
Mozilla实现 - Rhino,SpiderMonkey,- 具有不同的行为。它们的语法包含一个非标准的函数语句,这意味着函数将在运行时进行计算,而不是在解析时进行计算,就像在 s 中发生的那样。在这些实现中,我们将定义第一个函数。FunctionDeclaration
函数可以用不同的方式声明,比较以下内容:
1- 使用赋给变量乘法的函数构造函数定义的函数:
var multiply = new Function("x", "y", "return x * y;");
2- 名为乘法的函数的函数声明:
function multiply(x, y) {
return x * y;
}
3- 分配给变量乘法的函数表达式:
var multiply = function (x, y) {
return x * y;
};
4- func_name命名函数表达式,分配给变量乘法:
var multiply = function func_name(x, y) {
return x * y;
};