はじめに
この記事を読めば、JavaScriptのクロージャを使いこなすことができるようになります。
●クロージャとは
○クロージャの基本概念
クロージャとは、関数とその関数がアクセスできる外部変数をひとまとめにしたものです。
これにより、関数内で定義された変数が、関数の実行が終了しても保持されるようになります。
●クロージャの使い方
○サンプルコード1:カウンター機能
クロージャを使って簡単なカウンター機能を実装します。
function createCounter() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3
○サンプルコード2:プライベート変数の実現
クロージャを利用してプライベート変数を実現します。
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function () {
return _name;
},
getAge: function () {
return _age;
},
};
}
const person = createPerson("John Doe", 30);
console.log(person.getName()); // "John Doe"
console.log(person.getAge()); // 30
○サンプルコード3:イベントリスナーのスコープ
イベントリスナーでクロージャを利用し、変数のスコープを制限します。
document.querySelector("#button").addEventListener("click", (function () {
let count = 0;
return function () {
count++;
console.log("Button clicked " + count + " times.");
};
})());
○サンプルコード4:タイマー機能
クロージャを使ってタイマー機能を実装します。
function createTimer() {
let startTime = Date.now();
return function () {
const elapsedTime = Date.now() - startTime;
console.log("Elapsed time: " + elapsedTime + "ms");
};
}
const timer = createTimer();
setTimeout(() => {
timer(); // Elapsed time: 経過時間(ms)が表示される
}, 1000);
○サンプルコード5:メモ化
クロージャを利用して、計算結果をキャッシュするメモ化を実装します。
function memoize(fn) {
const cache = {};
return function (arg) {
if (cache[arg]) {
return cache[arg];
}
const result = fn(arg);
cache[arg] = result;
return result;
};
}
function factorial(n) {
if (n === 0) {
return 1;
}
return n * factorial(n - 1);
}
const memoizedFactorial = memoize(factorial);
console.log(memoizedFactorial(5)); // 120
console.log(memoizedFactorial(5)); // 120 (キャッシュから取得)
○サンプルコード6:モジュールパターン
クロージャを利用したモジュールパターンを実装します。
const myModule = (function () {
let privateVar = "I am private.";
function privateMethod() {
console.log(privateVar);
}
return {
publicMethod: function () {
privateMethod();
},
};
})();
myModule.publicMethod(); // "I am private."
○サンプルコード7:一度だけ実行する関数
クロージャを使って、一度だけ実行される関数を作成します。
function createOnce(fn) {
let called = false;
return function () {
if (!called) {
called = true;
return fn.apply(this, arguments);
}
};
}
const logOnce = createOnce(console.log);
logOnce("Hello!"); // "Hello!"
logOnce("Hello!"); // 何も表示されない
●クロージャの注意点と対処法
○メモリリークの対策
クロージャは、変数が保持され続けるため、メモリリークの原因になることがあります。
適切なタイミングでクロージャを解放することで、メモリリークを防ぐことができます。
●クロージャの応用例とサンプルコード
○サンプルコード8:デコレータパターン
クロージャを使ったデコレータパターンを実装します。
function withLogging(fn) {
return function () {
console.log("Executing " + fn.name);
return fn.apply(this, arguments);
};
}
function add(a, b) {
return a + b;
}
const loggedAdd = withLogging(add);
console.log(loggedAdd(1, 2)); // "Executing add" と表示され、結果は 3
○サンプルコード9:イベントデリゲーション
クロージャを利用してイベントデリゲーションを実装します。
document.querySelector("#parent").addEventListener("click", function (event) {
if (event.target.matches(".child")) {
console.log("Child element clicked:", event.target);
}
});
○サンプルコード10:スロットリング
クロージャを使ってスロットリングを実装します。
function throttle(fn, delay) {
let lastCall = 0;
return function () {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
return fn.apply(this, arguments);
}
};
}
function onScroll() {
console.log("Scroll event detected.");
}
window.addEventListener("scroll", throttle(onScroll, 500));
まとめ
この記事では、JavaScriptのクロージャについて初心者向けに解説し、10の使い方とサンプルコードを紹介しました。
クロージャを使いこなすことで、より効率的で保守性の高いコードを書くことができます。
ぜひこの記事を参考に、クロージャを活用したプログラミングを楽しんでください。