こんにちは。フロントエンドの開発といえばJavaScript。
ただ、JavaScriptの関数には、通常の関数定義以外にも、関数リテラル、無名関数、アロー関数などいろいろな種類があって初心者が戸惑うポイントでもあります。
ちょっと強引な言い方ですが、これらは見た目が違うだけで機能は同じです。
そんな中で、今回取り上げる『即時関数』はちょっと異彩を放っています。
というのも、それは『変数のスコープ』が関係しているからです。
この記事では、JavaScriptの即時関数の定義と目的について、具体例も挙げて解説します。
『変数のスコープ』についても理解が深まり、初心者脱出の手がかりとなるはずです。
JavaScriptの即時関数とは
即時関数とは、その名が示すとおり、「定義されて即時に実行される関数」です。
即実行されるので、実行されるのは1回になります。
具体的な記述方法は2通りあります。
// 記述方法その1
(function() {
// 関数で実行すること…
})();
// 記述方法その2(JSLintではこちらが推奨)
(function() {
// 関数で実行すること…
}());
JSLintでは後者が推奨されていますが、どちらも同じだと思っていただいて構いません(この記事では前者の方法で記述します)。
引数を渡す場合は以下の様になります。
(function(parameter1, parameter2, ...) {
// 関数で実行すること…
})('hoge', 'fuga', ...);
また、通常の関数同様、戻り値も持たせることができます。
const result = (function(parameter1, parameter2) {
return parameter1 * parameter2;
})(1, 2);
console.log(result); // 2が出力される
さらに、これをアロー関数を用いて以下の様に書くこともできます。
const result = ((parameter1, parameter2) => {
return parameter1 * parameter2;
})(1, 2);
console.log(result); // 2が出力される
即時関数を使う理由

さて、「即時関数は実行されるのは1回」と聞いて、
「あれ?関数って汎用的な機能をまとめて使い回しするものなのに…」
と不思議に思った方もおられるのではないでしょうか。
その通りです。即時関数には大切な目的・使う理由があるのです。
それは『スコープを汚染させない』です。
以下に説明していきます。
ところで、『スコープ』とは
スコープとは『変数が扱える範囲』です。このため『変数のスコープ』とあえて言うこともあります。
「この変数が使えるのは、ここからここまでで、そっちでは使えません」
というものです。
こんな決まりがあるのは、同じ変数名を意図しない用途で使ってしまうとエラーの原因となってしまうからです。
例えば、鈴木さんという家に太郎さんという男の子がいたとします。
太郎さんに弟が生まれたとき、この弟さんにも太郎という名前を付けてしまうと、鈴木家で「おーい太郎!」と呼んだ時に混乱が起こります。
しかし、おとなりの山田さんの家に生まれた男の子になら太郎と名付けても、鈴木家、山田家のどちらにも太郎さんに関する混乱は起きません。
この『鈴木家』『山田家』というのが『スコープ』になります。
さらに、『鈴木家』での変更は『山田家』には影響がありません。
鈴木家の太郎さんが髪を切ろうが、ひげを伸ばそうが、山田家の太郎さんには何の影響もないのです。
つまり、変数の扱える範囲を限定することで変更や修正、影響の範囲も限定することができ、ソースコードの保守性や再利用性も上がるのです。
JavaScriptのスコープ
ちょっと規模の大きい開発をするとき、多人数で開発するとき、開発効率や保守性をあげるために機能をカプセル化する必要があります。
そのために、変数の扱える範囲を限定する『変数のスコープ』が必須です。
とろこが、JavaScriptにはグローバルスコープと関数スコープの2つしかありません。
グローバルスコープはその名前の通りプログラム全体が範囲となりますので、機能のカプセル化には関数スコープを利用するしかありません。
即時関数を使ってラップする
そこで即時関数を使うのです。分割した機能を即時関数でラップしてあげます。
その即時関数の中で、初期化と必要な処理をラップしてあげればカプセル化の完成です。
具体的には以下のようなものです。
const buttonModule =(() => {
let counter = 0; // 初期化
// 必要な処理
return {
countUp: () => {
counter+=1
},
showCounter: () => {
console.log(counter)
}
}
})();
これはアロー関数を使った即時関数でbuttonModuleという『カプセル』(オブジェクトと言います)を作ったものです。
ここで使われているcounterという変数は、このカプセル内だけで有効で、このカプセルを利用したプログラムのどの部分にも影響を及ぼしません。
これが『スコープを汚染させない』ということであり、即時関数を利用する主要な目的です。
即時関数はこの例のようにオブジェクトの生成の他に
- ページ読込時の初期化
- DOM要素へのイベント処理
などの『一回だけ』『グローバルスコープを汚染させない』必要があるときに使用されます。
まとめ
今回の記事をまとめます。
- JavaScriptの関数はいろいろありますが、見た目とコーディングのしやすさの違いでしかない
- その中で即時関数は、グローバルスコープを汚染しないという目的で使われる
- 具体的には、オブジェクトの生成、ページ読込時の初期化、DOM要素へのイベント処理のような、一回だけ必要なグローバルスコープを汚染させない処理に使用される
となります。