最近、Javascript をたくさん読んでいるのですが、インポートする .js ファイルではファイル全体が次のようにラップされていることに気づきました。
(function() {
...
code
...
})();
単純なコンストラクター関数のセットではなく、これを行う理由は何ですか?
ベストアンサー1
これは通常、名前空間 (後述) を設定し、メンバー関数や変数の可視性を制御するためのものです。オブジェクト定義のようなものだと考えてください。技術的な名前は、即時呼び出し関数式(IIFE) です。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()
実行するには と実行するだけです。しかし、上記の例では、関数を定義するだけではなく、定義と呼び出しを 1 回で実行します。つまり、JavaScript ファイルが読み込まれると、すぐに実行されます。もちろん、次のようにすることもできます。
function globalFunction() {
// code
}
globalFunction();
動作は、1 つの大きな違いを除いてほぼ同じです。IIFE を使用すると、グローバル スコープが汚染されることが回避されます (結果として、関数に名前がないため、関数を複数回呼び出すことはできませんが、この関数は 1 回だけ実行されることを意図しているため、実際には問題にはなりません)。
IIFE の優れた点は、内部で定義して、必要な部分だけを外部に公開できることです (基本的に独自のライブラリ/プラグインを作成できる名前空間の例):
var myPlugin = (function() {
var private_var;
function private_function() {
}
return {
public_function1: function() {
},
public_function2: function() {
}
}
})()
これで、 を呼び出すことはできますmyPlugin.public_function1()
が、 にアクセスすることはできませんprivate_function()
。これはクラス定義と非常によく似ています。これをよりよく理解するには、次のリンクを参照してさらに読むことをお勧めします。
編集
言い忘れていました。final では()
、内部に必要なものをすべて渡すことができます。たとえば、jQuery プラグインを作成するときは、次のようにjQuery
または を渡します。$
(function(jQ) { ... code ... })(jQuery)
つまり、ここで行っているのは、1 つのパラメータ ( と呼ばれるjQ
ローカル変数で、その関数だけが知っている) を受け取る関数を定義することです。次に、関数を自己呼び出ししてパラメータ ( とも呼ばれますjQuery
が、これは外部からのものであり、実際の jQuery 自体への参照です) を渡します。これを行う必要性は特にありませんが、次のような利点があります。
- グローバル パラメータを再定義し、ローカル スコープで意味のある名前を付けることができます。
- スコープ チェーンをたどってグローバル スコープまで移動するよりも、ローカル スコープで検索する方が高速なので、パフォーマンスがわずかに向上します。
- 圧縮(縮小)にはメリットがあります。
先ほど、これらの関数が起動時に自動的に実行される方法について説明しましたが、自動的に実行される場合、誰が引数を渡すのでしょうか。この手法では、必要なすべてのパラメータがすでにグローバル変数として定義されていることを前提としています。したがって、jQuery がグローバル変数として定義されていない場合、この例は機能しません。ご想像のとおり、jquery.js が初期化中に行うことの 1 つは、'jQuery' グローバル変数と、より有名な '$' グローバル変数を定義することです。これにより、jQuery が組み込まれた後でもこのコードが機能します。