JavaScript アドバンス

JavaScript の即時実行関数式

1. 即時実行関数式(IIFE)とは

IIFE は、Immediately Invoked Function Expression(即時実行関数式)の略称です。
その名の通り、定義されると同時に 自分自身を呼び出して実行する 関数のことを指します。

通常、関数は呼び出されたときにのみ実行されますが、IIFE は JavaScript エンジンがコードを読み込んだ(コンパイルした)時点で自動的に実行されます。

1.1 IIFE の基本構造

(function () {
  // すぐに実行したいコード
})();

IIFE は定義と実行を同時に行います。

2. IIFE が使用されるケース

IIFE は主に以下のような目的で使用されます。

  • プライベートスコープ(Private Scope) を作成するため
  • 初期化用の セットアップコード を一度だけ実行するため
  • 比較的古い JavaScript コードの保守

3. グローバルスコープの汚染を防ぐ

IIFE の内部にあるものはすべて、その関数内でのみ有効なプライベートなものとなります。
IIFE の中で定義された変数には、外部からアクセスすることはできません。

3.1 変数のカプセル化

(function () {
  let x = 10;
})();

// ここで x にアクセスすることはできません

(function () {
  let hidden = 42;
})();

let result = hidden; // ⛔ エラー: hidden は定義されていません

3.2 シンプルな匿名 IIFE

名前のない関数による自己実行の例です。

(function () {
  let text = "こんにちは!自分自身を呼び出しました。";
})();

4. IIFE の仕組み

「関数式(Function Expression)」を自己実行可能な形に変換することで IIFE は機能します。

1. 関数単体の場合

function () {
  // 実行コード
};

2. 式(Expression)への変換
関数全体を 括弧(Parentheses) で囲むことで、JavaScript に「これは関数宣言ではなく式である」と認識させます。

(function () {
  // 実行コード
});

3. 即時実行の追加
式の直後に () を付けることで、その式(関数)を即座に実行(インボーク)します。

(function () {
  // 実行コード
})();

重要: 自己実行できるのは「関数式」のみです。「関数宣言(Function Declaration)」を直接自己実行することはできません。

5. パラメータを持つ IIFE

IIFE に引数(Arguments)を渡すことも可能です。

5.1 実装例

(function (name) {
  let text = "こんにちは " + name;
})("田中 太郎");

5.2 戻り値を持つ IIFE

IIFE は値を返すことができ、その結果を変数に格納できます。

let result = (function () {
  return 5 + 5;
})();
// result の値は 10 となる

6. アロー関数による IIFE

モダンな記述である アロー関数(Arrow Functions) を使って IIFE を作成することもできます。

6.1 アロー関数の例

(() => {
  let text = "こんにちは!アロー関数の IIFE です。";
})();

6.2 パラメータ付きのアロー関数 IIFE

((name) => {
  let text = "こんにちは " + name;
})("佐藤 健一");

7. モダン JavaScript における IIFE

現在の JavaScript 開発では、モジュール(Modules) が IIFE の役割の多くを代替しています。
モジュールはデフォルトで独自のスコープを持っているため、グローバル汚染を心配する必要がありません。

7.1 モジュールスコープ

<script type="module">
let x = 10;
// この変数 x はモジュール内に限定され、グローバルではありません
</script>

8. 名前付き関数式の IIFE

IIFE に名前を付けることも可能です。

8.1 実装例

(function greet() {
  let text = "こんにちは!名前付きの IIFE です。";
})();

greet(); // ⛔ ReferenceError: greet は外部からは見えません

名前付きの greet は関数内部でのみ有効です。なぜ名前を付けるのでしょうか?
主な理由は、自己再帰(Recursion) を行うためです。

8.2 再帰的な IIFE の例(階乗計算)

(function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1); // 内部から自身を呼び出す
})(5);

9. モジュールとしての IIFE(プライベート変数)

クロージャを利用して、プライベートな変数を保持する「モジュールパターン」を作成できます。

9.1 カウンターの実装

const counter = (function () {
  let value = 0; // 外部からは直接書き換えられないプライベート変数
  return {
    increment() { value++; },
    get() { return value; }
  };
})();

counter.increment();
let x = counter.get(); // 1

10. IIFE の利用タイミングと注意点

即時実行関数は ECMAScript 6 (ES6) 以前の JavaScript で多用されてきましたが、現在は letconst、および モジュール の普及により、その必要性は減少しています。

現在でも有用なケース:

  • スクリプト読み込み時に即座に実行が必要なセットアップ処理
  • ライブラリ開発などで、グローバルスコープを絶対に汚染したくない場合
  • 古いブラウザ環境や、モジュールシステムを使えないレガシーな環境

使用を避けるべきケース:

  • モダンなモジュールシステム(ES Modules)が利用可能な環境
  • コードが複雑になり、可読性が損なわれる場合

IIFE の仕組みを理解しておくことは、既存のライブラリのソースコードを読み解いたり、スコープの概念を深く理解するために非常に重要です。