要約: このチュートリアルでは、JavaScript の即時起動関数の表現(IIFE)について学習します。
TL;DR
JavaScript の即時起動関数の表現は、式として定義され、作成直後に実行される 関数 です。次のように、即時起動関数の表現を定義する構文を示します。
(function(){
//...
})();
Code language: JavaScript (javascript)
IIFE の理由
関数 を定義すると、JavaScript エンジンは関数をグローバルオブジェクトに追加します。次の例を参照してください。
function add(a,b) {
return a + b;
}
Code language: JavaScript (javascript)
Web ブラウザでは、JavaScript エンジンは add()
関数を window
グローバルオブジェクトに追加します。
console.log(window.add);
Code language: JavaScript (javascript)
同様に、var
キーワードを使用して関数の外側に 変数 を宣言した場合、JavaScript エンジンは変数もグローバルオブジェクトに追加します。
var counter = 10;
console.log(window.counter); // 10
Code language: JavaScript (javascript)
グローバル変数と関数が多数ある場合、JavaScript エンジンはグローバルオブジェクトのスコープが失われるまで、それらに割り当てられたメモリだけを解放します。
その結果、スクリプトはメモリを非効率に使用する場合があります。さらに、グローバル変数と関数があると、名前の衝突が発生する可能性があります。
関数がグローバルオブジェクトを汚染しないようにする 1 つの方法は、即時起動関数の表現を使用することです。
JavaScript では、次の式を使用できます。
'This is a string';
(10+20);
Code language: JavaScript (javascript)
これらの式には効果がなくとも、この構文は正しく機能します。関数は式として宣言することもでき、関数表現と呼ばれます。
let sum = function(a, b) {
return a + b;
}
Code language: JavaScript (javascript)
この構文では、代入演算子(=
)の右側の部分は関数表現です。関数は式なので、括弧内にラップできます。
let sum = (function(a, b) {
return a + b;
});
Code language: JavaScript (javascript)
この例では、sum
変数は、2 つの引数を足す 匿名関数 として参照されます。
さらに、関数を作成直後に実行できます。
let sum = (function(a,b){
return a + b;
})(10, 20);
console.log(sum);
Code language: JavaScript (javascript)
この例では、sum
変数は関数呼び出しの結果を保持します。
関数は式として作成され、すぐに実行されるため、次の式を即時起動関数の表現(IIFE)と呼びます。
(function(a,b){
return a + b;
})(10,20);
Code language: JavaScript (javascript)
IIFE を定義するための一般的な構文を次に示します。
(function(){
//...
})();
Code language: JavaScript (javascript)
矢印関数 を使用して IIFE を定義できることにも注意してください。
(() => {
//...
})();
Code language: JavaScript (javascript)
関数 と 変数 を即時起動関数の表現内に配置することで、グローバルオブジェクトに対する汚染を回避できます。
(function() {
var counter = 0;
function add(a, b) {
return a + b;
}
console.log(add(10,20)); // 30
}());
Code language: JavaScript (javascript)
名前付き IIFE
IIFE には名前を付けることができます。ただし、実行後に再び呼び出すことはできません。
(function namedIIFE() {
//...
})();
Code language: JavaScript (javascript)
セミコロン(;)で始まる IIFE
時にセミコロン(;)で始まる IIFE を目にすることがあります。
;(function() {
/* */
})();
Code language: JavaScript (javascript)
この構文では、2 つ以上の JavaScript ファイルが盲目的に単一のファイルに連結される場合に、文を終了するためにセミコロンが使用されます。
たとえば、IIFE を使用する lib1.js
と lib2.js
という 2 つのファイルがある場合があります。
(function(){
// ...
})()
(function(){
// ...
})()
Code language: JavaScript (javascript)
コードバインダツールを使用して両方のファイルのコードを1つのファイルに連結する場合、セミコロン(;
)がないと連結されたJavaScriptコードは構文エラーが発生します。
実稼働中のIIFE
以下の関数を備えたcalculator.jsというライブラリがあるものとします
function add(a, b) {
return a + b;
}
function mutiply(a, b) {
return a * b;
}
Code language: JavaScript (javascript)
そして、HTMLドキュメントにcalculator.js
を読み込みます。
その後、別にもう1つのJavaScriptライブラリであるapp.js
を同じドキュメントに読み込む必要があると思います
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>JavaScript IIFE</title>
</head>
<body>
<script src="calculator.js"></script>
<script src="app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
app.js
にもadd()
関数があります
function add() {
return 'add';
}
Code language: JavaScript (javascript)
HTMLドキュメントでadd()
関数を使用すると、2つの数字の合計ではなく'add'
文字列が返されます
let result = add(10, 20);
console.log(result); // 'add'
Code language: JavaScript (javascript)
これは、app.js
のadd()
関数がcalculator.js
ライブラリのadd()
関数をオーバーライドするためです。
これを修正するには、calculator.jsで次のようにIIFEを適用できます
const calculator = (function () {
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
return {
add: add,
multiply: multiply
}
})();
Code language: JavaScript (javascript)
IIFEは、add()
とmultiply()
関数を参照するadd
メソッドとmultiply
メソッドを含むオブジェクトを返します。HTMLドキュメントでは、calculator.js
ライブラリを次のように使用できます
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>JavaScript IIFE</title>
</head>
<body>
<script src="js/calculator.js"></script>
<script src="js/app.js"></script>
<script>
let result = calculator.add(10, 20); // add in app.js
console.log(result); // 30
console.log(add()); // add in the app.js
</script>
</body>
</html>
Code language: HTML, XML (xml)
calculator.add()
はcalculator.js
によってエクスポートされたadd()
関数を呼び出し、add()
関数への2番目の呼び出しはapp.js
のadd()
関数を参照します。
jQueryとIIFE
次のHTMLドキュメントはjQueryライブラリを使用します
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>JavaScript IIFE - jQuery</title>
</head>
<body>
<h1>jQuery Demo</h1>
<script src="https://code.jquery.com/jquery-3.4.1.slim.js"
integrity="sha256-BTlTdQO9/fascB1drekrDVkaKd9PkwBymMlHOiG+qLI=" crossorigin="anonymous"></script>
<script>
let counter = 1;
$('h1').click(function () {
$(this).text('jQuery Demo' + ' Clicked ' + counter++);
});
</script>
</body>
</html>
Code language: HTML, XML (xml)
jQueryライブラリをインポートすると、$
またはjQuery
オブジェクトを介して多くの便利なjQuery関数が利用できます。内部的には、jQueryはIIFEを使用して機能を公開しています。
こうすることで、jQueryは1つのグローバル変数($
)を使用するだけで、グローバルオブジェクトを汚染することなく多くの関数を公開できます。
次の例は、IIFE内でjQuery $オブジェクトを_に変更する方法を示しています
(function (_) {
let counter = 1;
_('h1').click(function () {
_(this).text('jQuery Demo' + ' Clicked ' + counter++);
});
})(jQuery);
Code language: JavaScript (javascript)
この例では、jQueryオブジェクトをIIFEに渡して、代わりに_
引数を使用しました。
このチュートリアルでは、JavaScriptのすぐに呼び出される関数式(IIFE)とその目的について学びました。