1. ホーム
  2. javascript

[解決済み] Javascriptのファイル全体を「(function(){ ... })()」のような無名関数で囲むのは何のためでしょうか?

2022-03-15 22:25:19

質問

最近、Javascriptをよく読むのですが、インポートする.jsファイルに以下のようにファイル全体がラップされていることに気づきました。

(function() {
    ... 
    code
    ...
})();

単純なコンストラクター関数のセットではなく、このような方法をとる理由は何でしょうか?

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

通常、名前空間(後述)を設定し、メンバ関数や変数の可視性を制御することになります。オブジェクトの定義のようなものだと思ってください。技術的な名称は 即座に呼び出される関数式 (jQueryのプラグインは通常このような書き方をしています。

Javascriptでは、関数を入れ子にすることができます。ですから、以下のようなものは合法です。

function outerFunction() {
   function innerFunction() {
      // code
   }
}

を呼び出すことができます。 outerFunction() が表示されますが innerFunction() のスコープに制限されます。 outerFunction() に対してプライベートであることを意味します。 outerFunction() . これは基本的に、Javascriptの変数と同じ原理です。

var globalVariable;

function someFunction() {
   var localVariable;
}

対応する。

function globalFunction() {

   var localFunction1 = function() {
       //I'm anonymous! But localFunction1 is a reference to me!
   };

   function localFunction2() {
      //I'm named!
   }
}

上記のシナリオでは globalFunction() はどこからでも呼び出せますが localFunction1 または localFunction2 .

と書いているときにやっていること (function() { ... })() つまり、最初の括弧の中のコードを関数リテラルにしているのです(つまり、"オブジェクト"全体が実際には関数であることを意味します)。その後で、関数を自己呼び出しているのです(最後の () ) を定義したところです。つまり、先ほども言ったように、プライベートなメソッド/関数やプロパティを持つことができるのが大きなメリットです。

(function() {
   var private_var;

   function private_function() {
     //code
   }
})();

最初の例では、明示的に globalFunction を名前で指定して実行します。つまり globalFunction() を実行してください。しかし、上記の例では、単に関数を定義しているわけではありません。 を一度に呼び出すことができます。つまり、JavaScriptファイルがロードされると、即座に実行されるのです。もちろん、そうすることもできる。

function globalFunction() {
    // code
}
globalFunction();

IIFEを使用すると、グローバルスコープを汚染しないようになります。(結果的に、名前を持たないので関数を複数回呼び出すことはできませんが、この関数は一度しか実行されないので、実際には問題にはなりません。)

IIFEで素晴らしいのは、内部で何かを定義し、必要な部分のみを外部に公開することもできる点です(ネームスペースの例で、基本的に独自のライブラリやプラグインを作成することができます)。

var myPlugin = (function() {
 var private_var;

 function private_function() {
 }

 return {
    public_function1: function() {
    },
    public_function2: function() {
    }
 }
})()

を呼び出すことができます。 myPlugin.public_function1() にアクセスすることはできません。 private_function() ! というわけで、クラス定義とかなり似ています。このことをよりよく理解するために、以下のリンク先を参照することをお勧めします。

EDIT

書き忘れました。その最後の () のように、内部に何でも渡すことができます。例えば、jQueryのプラグインを作るときには jQuery または $ というように

(function(jQ) { ... code ... })(jQuery) 

つまり、ここでやっていることは、1つのパラメータを受け取る関数 ( jQ というローカル変数、そして既知の だけ をその関数に送る)。そして、その関数を自己起動し、パラメータを渡します(これも jQuery が、しかし これ は外部からのもので、実際のjQueryそのものへの参照である)。 これを行う緊急の必要性はありませんが、いくつかの利点があります。

  • グローバルパラメータを再定義して、ローカルスコープで意味のある名前を付けることができます。
  • グローバルスコープに移動するよりもローカルスコープに移動した方が早いので、若干のパフォーマンス上の利点があります。
  • 圧縮(ミニフィケーション)のメリットがあります。

先ほど、これらの関数が起動時に自動的に実行されることを説明しましたが、自動的に実行されるのであれば、誰が引数を渡しているのでしょうか? このテクニックは、必要なパラメーターがすでにグローバル変数として定義されていることを前提にしている。ですから、もしjQueryがすでにグローバル変数として定義されていなければ、この例はうまくいかないでしょう。ご想像の通り、jquery.jsは初期化時に「jQuery」というグローバル変数と、より有名な「$」というグローバル変数を定義しており、これによりjQueryが組み込まれた後でもこのコードが動作するようになっています。