🆑

クロージャとIIFEの解説

2024/04/19に公開

クロージャ(Closure)とは

クロージャとは、内部関数が外部関数のスコープにアクセスできる機能のこと。内部関数は、外部関数の変数やパラメータに"閉じ込められた"状態になる

クロージャの例:

const secureBooking = function() {
  let passengerCount = 0;

  return function() {
    passengerCount++;
    console.log(`${passengerCount} passengers`);
  };
}

const booker = secureBooking();
booker(); // 1 passengers
booker(); // 2 passengers
booker(); // 3 passengers

この例では、secureBooking関数の中で定義されたpassengerCount変数に対して、返された無名関数(内部関数)がアクセスできている。通常、関数の実行が終了すると、その中で定義された変数は解放されるが、クロージャを使うことで変数を"閉じ込めた"状態を維持できる

クロージャの動作原理

クロージャが発生する理由は、JavaScriptのスコープチェインと関数の実行コンテキストにある。

  1. 関数が定義されると、その関数に属するスコープが作られる(関数スコープ)
  2. 関数が実行されると、実行コンテキストが作られ、スコープチェインが作成される
  3. スコープチェインは、現在のスコープから外側のスコープへと続く参照の連鎖
  4. 内部関数は、自身が定義された時のスコープチェインを記憶する
  5. 内部関数が外部関数の変数にアクセスできるのは、スコープチェインに外部関数のスコープが含まれているため

つまり、内部関数は自身の外側にある変数やパラメータにアクセスできるため、クロージャが発生する

クロージャのメリット

  1. プライベート変数の作成が可能
  2. 関数の状態を保持できる
  3. 関数の一部を引数として渡すことができる

クロージャに関する注意点

クロージャは便利な機能ですが、メモリ管理に注意が必要です。内部関数がスコープチェインを維持し続けるため、不要なクロージャを作ってしまうと、メモリリークの原因になる

したがって、内部関数を別の変数に代入したり、イベントリスナーに登録したりする場合は、明示的にnullを代入して参照を解放することが重要!

let myInnerFunc = null; // nullを代入して参照を解放

// イベントリスナーから削除する場合
someElement.removeEventListener('click', myInnerFunc);
myInnerFunc = null;

このようにクロージャの利用に注意を払えば、メモリリークを防ぐことができる!

IIFE (Immediately Invoked Function Expression)

IIFEとは、定義されたと同時に実行される関数のこと。主に以下の2つの形式がある

  1. 無名関数リテラルを括弧で囲む形式
(function() {
  console.log('This will never run again');
})();
  1. 矢印関数を使う形式
(() => console.log('This will never run again'))();

IIFEは一度だけ実行されるため、初期化処理などに利用される。IIFEの中で定義された変数は外部からアクセスできないため、グローバルスコープを汚染しない。

(function() {
  const isPrivate = 23;
  // 実行したい処理...
})();

console.log(isPrivate); // エラー: isPrivateは定義されていない

また、クロージャと組み合わせることで、プライベート変数やプライベートメソッドを持つモジュールを作成できる。

const myModule = (function() {
  const privateVar = 42;

  const publicMethod = function() {
    console.log(`Value is: ${privateVar}`);
  }

  return {
    publicMethod: publicMethod
  };
})();

myModule.publicMethod(); // Value is: 42

まとめ

  • クロージャとは、内部関数が外部関数のスコープにアクセスできる機能のこと
  • クロージャを使うことで、プライベート変数の作成や関数の状態保持が可能
  • クロージャはメモリ管理に注意が必要で、不要な参照を解放することが大切
  • IIFEは定義された直後に実行される関数のこと
  • IIFEを使うことで、グローバルスコープを汚染せずに変数やメソッドを隔離できる
  • IIFEとクロージャを組み合わせることで、プライベート変数やメソッドを持つモジュールを作成できる

Discussion