1. ホーム
  2. javascript

[解決済み] カプセル化された匿名関数の構文について説明します。

2022-03-26 13:48:55

質問

概要

JavaScriptでカプセル化された匿名関数の構文の理由を説明できますか?なぜこれが機能するのか。 (function(){})(); しかし、これはそうではありません。 function(){}(); ?


知っていること

JavaScriptでは、このように名前付き関数を作成します。

function twoPlusTwo(){
    alert(2 + 2);
}
twoPlusTwo();

また、無名関数を作成して変数に代入することも可能です。

var twoPlusTwo = function(){
    alert(2 + 2);
};
twoPlusTwo();

匿名関数を作成し、それを括弧で囲んですぐに実行することで、コードのブロックをカプセル化することができます。

(function(){
    alert(2 + 2);
})();

モジュール化されたスクリプトを作成する際に、GreasemonkeyスクリプトやjQueryプラグインなどのように、現在のスコープやグローバルスコープに競合する可能性のある変数が散乱しないようにするために有効です。

さて、なぜこれがうまくいくのか、理解できました。括弧は内容を囲み、結果のみを公開します(もっと良い表現があると思います)。 (2 + 2) === 4 .


わからないこと

しかし、なぜこれが同じように機能しないのか、理解できない。

function(){
    alert(2 + 2);
}();

それを説明してもらえますか?

どのように解決するのですか?

としてパースされているため、うまくいきません。 FunctionDeclaration であり、関数宣言の名前識別子は 必須 .

括弧で囲むと、それは次のように評価されます。 FunctionExpression また、関数式には名前を付けることも、付けないこともできます。

の文法は FunctionDeclaration はこのようになります。

function Identifier ( FormalParameterListopt ) { FunctionBody }

そして FunctionExpression s:

function Identifieropt ( FormalParameterListopt ) { FunctionBody }

ご覧のように Identifier (識別子 オプト )トークンを FunctionExpression は省略可能なので、名前が定義されていない関数式を持つことができます。

(function () {
    alert(2 + 2);
}());

または という名前 関数式になります。

(function foo() {
    alert(2 + 2);
}());

括弧(正式名称は グループ化演算子 ) は式だけを囲むことができ、関数式は評価されます。

この2つの文法プロダクションは曖昧で、例えば全く同じに見えることもある。

function foo () {} // FunctionDeclaration

0,function foo () {} // FunctionExpression

パーサーは、それが FunctionDeclaration または FunctionExpression に依存しています。 コンテキスト が表示されます。

上記の例では、2番目は式なので カンマ演算子 は、式だけを扱うこともできます。

一方 FunctionDeclaration は、実際には"と呼ばれるものにしか出現しない可能性があります。 Program つまり、グローバルスコープの外側にあるコードと、グローバルスコープの内側の FunctionBody 他の関数の

ブロック内の関数は、予測できない動作につながる可能性があるため、避ける必要があります。

if (true) {
  function foo() {
    alert('true');
  }
} else {
  function foo() {
    alert('false!');
  }
}

foo(); // true? false? why?

上記のコードで実際に生成されるのは SyntaxError というのは Block はステートメントしか含むことができませんが (ECMAScript 仕様では関数ステートメントは定義されていません)、ほとんどの実装では許容されており、単に 2 番目の関数、つまり 'false!' .

Mozillaの実装であるRhino、SpiderMonkeyは、異なる動作をしています。彼らの文法には 非標準の 関数ステートメント、つまり関数は 実行時 のようにパース時ではありません。 FunctionDeclaration s. これらの実装では、最初に定義された関数を取得することになります。


関数はさまざまな方法で宣言することができます。 は次のように比較します。 :

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;
};