FunctionDeclaration
として解析されており、関数宣言の名前識別子が必須であるため、機能しません。
括弧で囲むと として評価され、FunctionExpression
関数式に名前を付けても付けなくてもかまいません。
a の文法はFunctionDeclaration
次のようになります。
function Identifier ( FormalParameterListopt ) { FunctionBody }
そしてFunctionExpression
:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
ご覧のとおり、Identifier
(Identifier opt ) トークンFunctionExpression
はオプションであるため、名前を定義せずに関数式を使用できます。
(function () {
alert(2 + 2);
}());
または名前付き関数式:
(function foo() {
alert(2 + 2);
}());
括弧 (正式には Grouping Operatorと呼ばれます) は式のみを囲むことができ、関数式が評価されます。
2 つの文法生成はあいまいになる可能性があり、まったく同じに見える可能性があります。次に例を示します。
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
パーサーは、出現するコンテキストに応じて、それがFunctionDeclaration
かかを認識します。FunctionExpression
上記の例では、コンマ演算子も式のみを処理できるため、2 番目の例は式です。
一方、 s は実際には " " コードと呼ばれるもの、つまりグローバル スコープの外側のコード、および他の関数の内側FunctionDeclaration
にのみ現れる可能性があります。Program
FunctionBody
ブロック内の関数は、予測できない動作を引き起こす可能性があるため、避ける必要があります。
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
上記のコードは、実際には a を生成する必要がありますSyntaxError
。これは、 a にBlock
はステートメントのみを含めることができる (そして、ECMAScript 仕様では関数ステートメントを定義していないため) ため'false!'
です。
Mozilla の実装 (Rhino、SpiderMonkey) は、異なる動作をします。それらの文法には非標準のFunction ステートメントが含まれています。これは、関数が s の場合のように解析時ではなく、実行時FunctionDeclaration
に評価されることを意味します。これらの実装では、定義された最初の関数を取得します。
関数はさまざまな方法で宣言できます。以下を比較してください。
1-変数Multiplyに割り当てられたFunctionコンストラクターで定義された関数:
var multiply = new Function("x", "y", "return x * y;");
2- multiplyという名前の関数の関数宣言:
function multiply(x, y) {
return x * y;
}
3- 変数multiplyに割り当てられた関数式:
var multiply = function (x, y) {
return x * y;
};
4- 変数Multiplyに割り当てられた名前付き関数式func_name :
var multiply = function func_name(x, y) {
return x * y;
};