🆑
クロージャとIIFEの解説
クロージャ(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のスコープチェインと関数の実行コンテキストにある。
- 関数が定義されると、その関数に属するスコープが作られる(関数スコープ)
- 関数が実行されると、実行コンテキストが作られ、スコープチェインが作成される
- スコープチェインは、現在のスコープから外側のスコープへと続く参照の連鎖
- 内部関数は、自身が定義された時のスコープチェインを記憶する
- 内部関数が外部関数の変数にアクセスできるのは、スコープチェインに外部関数のスコープが含まれているため
つまり、内部関数は自身の外側にある変数やパラメータにアクセスできるため、クロージャが発生する
クロージャのメリット
- プライベート変数の作成が可能
- 関数の状態を保持できる
- 関数の一部を引数として渡すことができる
クロージャに関する注意点
クロージャは便利な機能ですが、メモリ管理に注意が必要です。内部関数がスコープチェインを維持し続けるため、不要なクロージャを作ってしまうと、メモリリークの原因になる
したがって、内部関数を別の変数に代入したり、イベントリスナーに登録したりする場合は、明示的にnullを代入して参照を解放することが重要!
let myInnerFunc = null; // nullを代入して参照を解放
// イベントリスナーから削除する場合
someElement.removeEventListener('click', myInnerFunc);
myInnerFunc = null;
このようにクロージャの利用に注意を払えば、メモリリークを防ぐことができる!
IIFE (Immediately Invoked Function Expression)
IIFEとは、定義されたと同時に実行される関数のこと。主に以下の2つの形式がある
- 無名関数リテラルを括弧で囲む形式
(function() {
console.log('This will never run again');
})();
- 矢印関数を使う形式
(() => 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