クロージャ
クロージャはありふれた概念であり、開発の過程でしばしば遭遇するものです。実際のところ、クロージャは複雑なものではありません。ただ、その概念が少し複雑なだけなのです。
クロージャの概念と機能
- クロージャ: ファンクションは、その周りのステートへの参照とともに束ねられ、クロージャを形成します。
- 特徴:関数の内部関数を別のスコープから呼び出して、その関数のメンバにアクセスすることができます。
コード例1
function makeFn() {
let msg = "hello fn";
return function () {
console.log(msg);
};
}
const fn = makeFn();
fn();
ここで、const fn = makeFn()というコードが実行され、fn が makeFn 関数内で reutrn される関数となり、外部 fn が makeFn から返された関数への参照を持ち、それが makeFn の msg 変数にアクセスすることがわかります。これでクロージャが作成されます。
コード例2
// once 一度だけ実行する関数を生成する
function once(fn) {
let done = false; // fnが実行されたかどうかを記録する
return function () {
if (!done) {
done = true;
fn.apply(this, arguments); // argumentsの詳細は、前の行の関数のパラメーターを指している。
}
};
}
//
let pay = once(function (money) {
console.log(`に支払われる:${money} RMB`);
});
pay(5); // プリントアウトは5人民元を支払う。
pay(6); // は実行されない。
pay(3); // は実行されない。
クロージャの性質
関数は実行されるとヒープ上に置かれ、終了するとヒープから取り除かれますが、ヒープ上のスコープ付きメンバは外部から参照されているため解放できず、内部関数はまだ外部関数のメンバにアクセスできます。
クロージャの例
// ある数、例えば2のべき乗を常に求めようとしているとしよう。
// 2番目のパラメーターが何度も何度も出現しているのがわかるだろう。,
// クロージャの2/3乗/4乗を求める関数を生成する関数を書くことができる。
// Math.pow(4, 2)
// Math.pow(3, 2)
/**
* べき乗関数を生成する
* @param { } power
*/
function makePower(power) {
return function (num) {
return Math.pow(num, power); // (2) パワークロージャー
};
}
//
let power2 = makePower(2);
// 3乗を求める
let power3 = makePower(3);
console.log(power2(2)); // 4 (1)
console.log(power2(3)); // 9
console.log(power3(2)); // 8
console.log(power2(2))
コードがマークされた位置まで実行されたら、F11キーを押してマークされた位置に入り、デバッグツールバーのスコープに「Closure」という文字が表示されるのがよくわかります。
そのため、デバッグ時に、どこでクロージャが発生したのか、また、その詳細がはっきりとわかります。