ここでは、WeakMap / WeakSet と Map / Set の違いをステップ実演で理解できる
「挙動比較シミュレーション」シナリオ付きデモを紹介します。
目的
同じように add() や set() をしても、
WeakMap / WeakSet では「オブジェクトしかキー・値に使えない」「GC(ガベージコレクション)で自動削除される」など、
Map / Set と根本的に違う性質を理解すること。
See the Pen WeakMap / WeakSet Comparison Demo by MONO365 -Color your days- (@monoqlo365) on CodePen.
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WeakMap / WeakSet 比較デモ</title>
<style>
body {
font-family: "Segoe UI", sans-serif;
background: #f8fafc;
color: #333;
text-align: center;
padding: 30px;
}
h1 { color: #0078d7; }
.container {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}
.panel {
width: 45%;
background: white;
border-radius: 12px;
border: 2px solid #0078d7;
padding: 15px;
box-shadow: 0 3px 8px rgba(0,0,0,0.1);
}
h2 {
background: #0078d7;
color: white;
border-radius: 6px;
padding: 5px;
}
button {
padding: 8px 14px;
margin: 6px;
border: none;
border-radius: 8px;
background: #0078d7;
color: white;
font-weight: bold;
cursor: pointer;
}
button:hover { background: #005fa3; }
.log {
background: #f0f9ff;
text-align: left;
padding: 10px;
border-left: 5px solid #0078d7;
border-radius: 8px;
height: 160px;
overflow-y: auto;
font-size: 0.9em;
margin-top: 10px;
}
.highlight { background: #fff7c2; }
</style>
</head>
<body>
<h1>🧩 Map / Set vs WeakMap / WeakSet 比較シミュレーション</h1>
<p>同じ操作を4種類に対して実行して、違いを体感してみよう!</p>
<div class="container">
<div class="panel">
<h2>🗺️ Map</h2>
<div id="mapLog" class="log"></div>
</div>
<div class="panel">
<h2>🔢 Set</h2>
<div id="setLog" class="log"></div>
</div>
<div class="panel">
<h2>🌿 WeakMap</h2>
<div id="weakMapLog" class="log"></div>
</div>
<div class="panel">
<h2>🍃 WeakSet</h2>
<div id="weakSetLog" class="log"></div>
</div>
</div>
<br>
<button id="startDemo">▶ 実演スタート</button>
<script>
const mapLog = document.getElementById("mapLog");
const setLog = document.getElementById("setLog");
const weakMapLog = document.getElementById("weakMapLog");
const weakSetLog = document.getElementById("weakSetLog");
function log(el, msg) {
el.innerHTML += msg + "<br>";
el.scrollTop = el.scrollHeight;
}
const myMap = new Map();
const mySet = new Set();
const myWeakMap = new WeakMap();
const myWeakSet = new WeakSet();
document.getElementById("startDemo").addEventListener("click", async () => {
mapLog.innerHTML = "";
setLog.innerHTML = "";
weakMapLog.innerHTML = "";
weakSetLog.innerHTML = "";
log(mapLog, "🧩 Map: 文字列キーもOK");
log(setLog, "🧩 Set: プリミティブ値もOK");
log(weakMapLog, "🌿 WeakMap: キーはオブジェクト限定!");
log(weakSetLog, "🍃 WeakSet: 値はオブジェクト限定!");
await step(800);
log(mapLog, `set("user", "Alice") ✅`);
myMap.set("user", "Alice");
log(setLog, `add("apple") ✅`);
mySet.add("apple");
log(weakMapLog, `set({}, "value") ✅`);
const obj1 = {id: 1};
myWeakMap.set(obj1, "value1");
log(weakSetLog, `add({name: "obj"}) ✅`);
const obj2 = {name: "obj"};
myWeakSet.add(obj2);
await step(1000);
log(mapLog, `Map.size = ${myMap.size}`);
log(setLog, `Set.size = ${mySet.size}`);
log(weakMapLog, `WeakMap は size がない(非列挙)`);
log(weakSetLog, `WeakSet も size がない(非列挙)`);
await step(1000);
log(weakMapLog, `<span class="highlight">obj1 への参照を破棄 → GC により削除される可能性</span>`);
log(weakSetLog, `<span class="highlight">obj2 への参照を破棄 → GC により削除される可能性</span>`);
await step(800);
// 擬似的にGCされたかのような表示
log(weakMapLog, `💨 obj1 は解放され、WeakMap から自動的に消える(実際のGCは見えない)`);
log(weakSetLog, `💨 obj2 もGCで削除される可能性`);
await step(1200);
log(mapLog, `🧾 Map は手動で delete() しない限り保持`);
log(setLog, `🧾 Set も手動で delete() しない限り保持`);
});
function step(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
</script>
</body>
</html>
HTML実演内容(ステップ概要)
| ステップ | 操作内容 | Map / Set の結果 | WeakMap / WeakSet の結果 |
|---|---|---|---|
| 1 | それぞれに要素を追加 | どんな値でもOK | オブジェクトのみOK |
| 2 | .size の確認 | 値が数で取得できる | 非列挙(size なし) |
| 3 | 参照を切る | 何も変化なし | GCで自動的に削除される可能性 |
| 4 | 明示的削除 | 手動で .delete() が必要 | 不要(GCに任せる) |
補足:WeakMap / WeakSet の性質
| 特徴 | Map / Set | WeakMap / WeakSet |
|---|---|---|
| キー/値にオブジェクト使用 | 任意 | オブジェクトのみ |
| size, keys, entries | 利用可 | 利用不可(非列挙) |
| 参照が切れると? | 残る | 自動削除(GC対象) |
| 主な用途 | データ保持、ループ処理など | キャッシュや一時的メモリ |
このシナリオでは、
🔹 ガベージコレクション(GC) の「見えない自動削除」を擬似アニメーションで体感できます。
🔹 4つのコレクションが同じ操作でどう違うかを並列で理解できます。


