以下は、WeakMapを使ってイベントリスナーをキャッシュし、メモリリークを防ぐ実践デモのコード例です。ブラウザで動作します。コメント入りで仕組みをわかりやすく説明しています。
目的
DOM要素をキーにしてイベントリスナーを管理する際、Mapだと要素を削除しても参照が残りガベージコレクションされない可能性があります。WeakMapを使うと、要素がDOMから削除されると自動で解放されます。
See the Pen WeakMap Event Listener Cache Demo by MONO365 -Color your days- (@monoqlo365) on CodePen.
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>WeakMap イベントリスナーキャッシュ デモ</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.btn { margin: 5px; padding: 10px 15px; border: 1px solid #888; cursor: pointer; }
#log { margin-top: 15px; white-space: pre-line; }
</style>
</head>
<body>
<h2>🔗 WeakMap でイベントリスナーをキャッシュ</h2>
<button id="add" class="btn">要素を追加</button>
<button id="remove" class="btn">要素を削除</button>
<div id="container"></div>
<div id="log"></div>
<script>
// --- WeakMap に「DOM要素 → イベントリスナー関数」を保存 ---
const listenerCache = new WeakMap();
const container = document.getElementById('container');
const log = document.getElementById('log');
document.getElementById('add').onclick = () => {
const btn = document.createElement('button');
btn.textContent = 'クリックしてみて!';
btn.className = 'btn';
// イベントリスナー作成
const listener = () => {
log.textContent += '✅ ボタンがクリックされました!\n';
};
// WeakMap にキャッシュ
listenerCache.set(btn, listener);
// イベント登録
btn.addEventListener('click', listener);
container.appendChild(btn);
log.textContent += '🟢 新しいボタンを追加しました。\n';
};
document.getElementById('remove').onclick = () => {
if (container.firstChild) {
const btn = container.firstChild;
// WeakMap から削除操作は不要!
// DOMから削除すると参照がなくなり、自動でGC対象になる。
container.removeChild(btn);
log.textContent += '🔴 ボタンを削除しました(GCに任せます)\n';
} else {
log.textContent += '⚠️ 削除する要素がありません。\n';
}
};
// ✅ 開発ツールのメモリプロファイラで確認すると、
// WeakMapを使うことでDOM削除後にリスナーも解放されるのが分かります。
</script>
</body>
</html>
HTML解説
| 比較項目 | Map | WeakMap |
|---|---|---|
| キーの型 | 何でも可 | オブジェクトのみ(DOM要素含む) |
| ガベージコレクション | 手動削除しない限り保持 | キーが破棄されると自動解放 |
| イテレーション(for…of等) | 可能 | 不可(内部情報は非公開) |
| メモリリーク防止 | ❌ 難しい | ✅ 自動的に解放される |
応用例
- イベントリスナーのキャッシュ
- DOMノードごとの一時データ(状態やカウントなど)
- ライブラリ内部の「非公開データ格納」


