它不能工作,因为它被解析为FunctionDeclaration,并且函数声明的名称标识符是强制性的。
当你用圆括号包围它时,它被计算为一个FunctionExpression,函数表达式可以命名也可以不命名。
FunctionDeclaration的语法是这样的:
function Identifier ( FormalParameterListopt ) { FunctionBody }
和FunctionExpressions:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
正如你所看到的,FunctionExpression中的Identifier (Identifieropt)令牌是可选的,因此我们可以有一个没有定义名称的函数表达式:
(function () {
alert(2 + 2);
}());
或命名函数表达式:
(function foo() {
alert(2 + 2);
}());
圆括号(正式称为分组操作符)只能包围表达式,函数表达式被求值。
这两个语法结果可以是模棱两可的,它们可以看起来完全相同,例如:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
解析器知道它是FunctionDeclaration还是FunctionExpression,这取决于它出现的上下文。
在上面的例子中,第二个是一个表达式,因为逗号操作符也只能处理表达式。
另一方面,FunctionDeclarations实际上只能出现在所谓的“程序”代码中,即全局作用域之外的代码,以及其他函数的FunctionBody内部的代码。
应该避免使用块中的函数,因为它们会导致不可预测的行为,例如:
If (true) {
函数foo() {
alert('真的');
}
}其他{
函数foo() {
alert('假! ');
}
}
foo ();/ /真的吗?假的?为什么?
上面的代码实际上应该产生一个SyntaxError,因为Block只能包含语句(ECMAScript规范没有定义任何函数语句),但大多数实现都是容忍的,并且只接受第二个函数,即警告“false!”的函数。
Mozilla的实现——rhino、SpiderMonkey——有不同的行为。它们的语法包含一个非标准的Function Statement,这意味着函数将在运行时计算,而不是在解析时计算,就像FunctionDeclarations一样。在这些实现中,我们将得到定义的第一个函数。
函数可以用不同的方式声明,比较以下几种:
用function构造函数定义的函数赋值给变量multiply:
var multiply = new Function("x", "y", "return x * y;");
2-一个名为multiply函数的函数声明:
function multiply(x, y) {
return x * y;
}
赋值给变量multiply的函数表达式:
var multiply = function (x, y) {
return x * y;
};
一个命名函数表达式func_name,赋值给变量multiply:
var multiply = function func_name(x, y) {
return x * y;
};