なぜ今さらIIFEなのか
フロントエンド開発の現場では、ES Modulesの普及により、かつてグローバル汚染を防ぐための「防波堤」として重宝されたIIFE(即時実行関数)の出番は激減しました。しかし、レガシーコードの保守や、特定のビルド環境におけるスコープの隔離において、IIFEは依然として強力なツールです。本稿では、単なる「古いテクニック」として片付けず、現代のアプリケーション開発における実践的な価値を再考します。
非同期処理におけるクロージャの活用
実務で遭遇する典型的なケースに、ループ内での非同期処理があります。例えば、APIリクエストをループ内で発行する際、カウンタ変数が期待通りに保持されない問題に対し、IIFEによるスコープの生成は現在でも有効な解決策です。
function processItems(items) {
for (let i = 0; i < items.length; i++) {
(function(index) {
setTimeout(() => console.log(items[index]), 1000);
})(i);
}
}
もちろん、現代では let を用いることでブロックスコープが生成されるため、このケースではIIFEは不要です。しかし、「特定の変数を関数のスコープ内に閉じ込め、即座に評価を完了させる」という挙動は、複雑なイベントハンドラの初期化や、ライブラリのプラグイン構成時に、副作用を最小限に抑えるための「カプセル化」として機能します。
メモリ管理と即時実行のメリット
IIFEの最大の利点は、名前を付けずに実行し、即座にガーベジコレクションの対象とできることです。大規模なフォームの初期化ロジックや、特定のコンポーネントがマウントされた瞬間に一度だけ実行したい複雑な設定処理を、関数として名前を定義せずに記述することで、グローバルな名前空間を汚染せず、かつメモリ上にも長期的に残さないという「使い捨ての実行環境」を構築できます。
現代的な代替案との使い分け
現在では、IIFEの役割の多くは ブロックスコープ({ … }) や ES Modules に代替されています。特に、単にスコープを区切りたいだけであれば、名前のないブロックを用いる方が可読性は高まります。
しかし、「値の即時評価」が必要な場合(例:定数の初期化において、複雑な計算が必要だが、その計算過程で一時的な変数を使いたい場合)は、依然としてIIFEが最もクリーンな手段です。
const CONFIG = (function() {
const base = fetchData();
return { …base, timestamp: Date.now() };
})();
このように、IIFEを「過去の遺物」と切り捨てるのではなく、「一時的なスコープと即時評価」という道具として理解しておくことが、フロントエンド・スペシャリストとしての引き出しを増やすことにつながります。保守性の高いコードを書くためには、技術の流行だけでなく、その背後にある「スコープとライフサイクル」の本質を理解し、状況に応じて適材適所で使い分ける姿勢が求められます。