はじめに
JavaScriptのクロージャの学習メモです。
誤りご指摘等あれば、気軽にコメントいただけると嬉しいです。
クロージャとは?
自分の言葉で簡単に表現してみると
「定義した関数の外側のスコープにある変数や関数を参照できる仕組み(または関数)」のこと
だと理解しました。
公式だとこのように書かれてました。
クロージャ
クロージャは、組み合わされた(囲まれた)関数と、その周囲の状態(レキシカル環境)への参照の組み合わせです。言い換えれば、クロージャは内側の関数から外側の関数スコープへのアクセスを提供します。JavaScript では、関数が作成されるたびにクロージャが作成されます。
クロージャのメリット
関数内などの変数や関数などを他のプログラムから簡単に変更されないように制御できること。
クロージャの実行サンプル
初期値の数値を引数で渡して、それをクロージャ関数(内部に定義した関数)から計算して、計算結果をコンソールに出力するサンプル。
※サンプルコードはTypeScript
で記述してます。が気にせず。
// 4つのクロージャ関数を生成して返す関数
function calcFactory(def: number) {
// ローカル変数result: calcFactory関数のスコープ内でしか参照できない
let result: number = def;
// この4つの関数たちがクロージャ
const plus = (num: number) => {
console.log("計算前", result);
result = result + num;
console.log("計算後", result);
};
const minus = (num: number) => {
console.log("計算前", result);
result = result - num;
console.log("計算後", result);
};
const multiply = (num: number) => {
console.log("計算前", result);
result = result * num;
console.log("計算後", result);
};
const divide = (num: number) => {
console.log("計算前", result);
result = result / num;
console.log("計算後", result);
};
// クロージャ関数を返す
return { plus, minus, multiply, divide };
}
// このタイミングでクロージャが生成される
const calc = calcFactory(10);
calc.plus(3);
calc.minus(5);
calc.multiply(8);
calc.divide(4);
このときcalcFactory関数
の中でしか参照できない変数result
に計算結果を保ちながら、処理が繰り返される。
変数result
にはクロージャ関数plus
minus
multiply
divide
からしか参照できない。
const calc = calcFactory(10);
calc.plus(3);
calc.minus(5);
calc.multiply(8);
calc.divide(4);
// クロージャを経由せずにresultを参照することはできない
calc.result; // エラー
関数が作成されるたびにクロージャが作成される
公式にもこのような記述がありますが、
JavaScript では、関数が作成されるたびにクロージャが作成されます。
どういうことかコードで確認してみる。
// このタイミングでdefに10をもつクロージャが生成される
const calc = calcFactory(10);
calc.plus(3);
calc.minus(5);
calc.multiply(8);
calc.divide(4);
console.log("--------------------------------------");
// このタイミングでdefに20をもつcalcとは異なるクロージャが生成される
const calc2 = calcFactory(20);
calc2.plus(3);
calc2.minus(5);
calc2.multiply(8);
calc2.divide(4);
calcFactory関数
を実行するたびに異なる(今回の場合は引数def
が違う数値を渡すことにより変数result
が異なる)クロージャが生成される。
最後に
大変有益でわかりやすい記事ばかりで助かりました!ありがとうございました!