WeakMap の基本 — new WeakMap()
WeakMap は「キーにオブジェクトだけを使える特殊なマップ」です。最大の特徴は キーとなるオブジェクトがガベージコレクション(不要メモリ解放)の対象になったら、自動的に WeakMap からも消える こと。これにより「オブジェクトに付随する追加情報」を安全に管理できます。
基本の使い方
const wm = new WeakMap();
const obj = { id: 1 };
wm.set(obj, "secret data");
console.log(wm.get(obj)); // "secret data"
console.log(wm.has(obj)); // true
// objを参照しなくなると、ガベージコレクション時にWeakMapからも消える
JavaScript- キー: 必ずオブジェクト(プリミティブ値は不可)。
- 値: 任意の型。
- メモリ管理: キーが不要になれば自動的に削除されるため、メモリリーク防止に役立つ。
WeakMap と Map の違い
| 特徴 | Map | WeakMap |
|---|---|---|
| キー | 任意(文字列、数値、オブジェクト) | オブジェクトのみ |
| ガベージコレクション | キーが残る | キーが解放されると自動削除 |
| 列挙 | for...of や keys() で列挙可能 | 列挙不可(内部を直接見ることはできない) |
| 用途 | 辞書、キャッシュ、順序付きデータ | オブジェクトに付随する「隠しデータ」管理 |
すぐ使えるテンプレート集
1) オブジェクトに付随する「秘密データ」を管理
const wm = new WeakMap();
function createUser(name) {
const user = { name };
wm.set(user, { loggedIn: false });
return user;
}
const u1 = createUser("Aki");
console.log(wm.get(u1)); // { loggedIn: false }
wm.get(u1).loggedIn = true;
console.log(wm.get(u1)); // { loggedIn: true }
JavaScript- ポイント: userオブジェクトが破棄されれば、WeakMapのデータも自動的に消える。
2) DOM要素に関連データを付ける
const wm = new WeakMap();
function bindData(el, data) {
wm.set(el, data);
}
function getData(el) {
return wm.get(el);
}
// 例: DOM要素に追加情報を紐付け
const div = document.createElement("div");
bindData(div, { clicked: 0 });
div.addEventListener("click", () => {
const d = getData(div);
d.clicked++;
console.log("clicked:", d.clicked);
});
JavaScript- ポイント: DOM要素が削除されれば WeakMap のデータも解放される。
3) クラスの「プライベートデータ」実装に利用
const privates = new WeakMap();
class Counter {
constructor() {
privates.set(this, { count: 0 });
}
inc() {
privates.get(this).count++;
}
get value() {
return privates.get(this).count;
}
}
const c = new Counter();
c.inc();
console.log(c.value); // 1
JavaScript- ポイント: 外部から直接
privatesにアクセスできないため、擬似的な「プライベート変数」として使える。
よくある落とし穴と対策
- キーはオブジェクトのみ: 文字列や数値をキーにするとエラー。
→ 対策: 必ず{}やクラスインスタンス、DOM要素などをキーに。 - 列挙できない:
for...ofやkeys()は使えない。
→ 対策: WeakMapは「内部を覗けない」設計。用途は「付随データの隠し管理」に限定。 - デバッグしにくい: 中身を確認できないため、ログ出力で追えない。
→ 対策: 必要なら Map を使う。WeakMapは「ガベージに強い参照」が必要な場面だけ。
練習問題(手を動かして覚える)
// 1) オブジェクトに秘密データを紐付け
const wm = new WeakMap();
const obj = {};
wm.set(obj, "hidden");
console.log(wm.get(obj)); // "hidden"
// 2) DOM要素にクリック回数を記録
const wm2 = new WeakMap();
const btn = document.createElement("button");
wm2.set(btn, { clicks: 0 });
btn.addEventListener("click", () => {
wm2.get(btn).clicks++;
console.log("clicks:", wm2.get(btn).clicks);
});
// 3) クラスのプライベートデータ
const priv = new WeakMap();
class User {
constructor(name) {
priv.set(this, { name });
}
getName() {
return priv.get(this).name;
}
}
const u = new User("Mao");
console.log(u.getName()); // "Mao"
JavaScript直感的な指針
- Map: 辞書や列挙可能なデータ管理。
- WeakMap: オブジェクトに付随する「隠しデータ」や「ガベージに強い参照」。
- 列挙不可・オブジェクト専用: 内部を覗けない設計なので、用途は限定的。
👉 WeakMap は「オブジェクトに秘密の付加情報を持たせたい」「メモリリークを避けたい」場面で使うのがベストです。
