ここでは、「Map」と「Object」の違いをアニメーション+図解で視覚的に理解できるHTMLデモ
として示します。
ポイント
- 両者の「キーの扱い」や「順序・型の違い」を一目で理解できるように
- Map は「任意の型キー+順序保持」
- Object は「文字列キーのみ+順序保証されにくい」
を、アニメーションで体感できるようにしました。
See the Pen “Map vs. Object Differences” Visual Comparison Animation 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>Map vs Object 視覚比較アニメーション</title>
<style>
body {
font-family: "Segoe UI", sans-serif;
background: #f9fafb;
color: #333;
text-align: center;
padding: 30px;
}
h1 { color: #0078d7; }
.area {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
margin-top: 30px;
gap: 20px;
}
.panel {
width: 45%;
background: #fff;
border: 2px solid #0078d7;
border-radius: 12px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
padding: 20px;
}
.panel h2 {
background: #0078d7;
color: white;
border-radius: 8px;
padding: 6px 0;
}
.pair {
margin: 8px auto;
width: 80%;
padding: 8px 10px;
background: #eef6ff;
border-radius: 6px;
text-align: left;
position: relative;
animation: fadeIn 0.5s ease;
}
.key {
color: #0078d7;
font-weight: bold;
}
.arrow {
color: #555;
margin: 0 6px;
}
.value {
color: #00b894;
}
.update {
background: #fff7d1 !important;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-5px); }
to { opacity: 1; transform: translateY(0); }
}
input {
padding: 8px;
border: 2px solid #0078d7;
border-radius: 8px;
margin: 5px;
}
button {
padding: 8px 14px;
border: none;
border-radius: 8px;
background: #0078d7;
color: white;
font-weight: bold;
cursor: pointer;
}
button:hover { background: #005fa3; }
.msg {
margin-top: 20px;
font-size: 1.1em;
}
.explain {
margin-top: 25px;
background: #eef;
border-left: 5px solid #0078d7;
padding: 15px;
border-radius: 8px;
text-align: left;
}
.highlight {
animation: pulse 0.6s ease;
}
@keyframes pulse {
0% { background-color: #fff; }
50% { background-color: #ffeb99; }
100% { background-color: #fff; }
}
</style>
</head>
<body>
<h1>🗺️ Map と 🧱 Object の違い(視覚アニメーション)</h1>
<p>Map は <strong>任意の型のキー</strong>を順序つきで保持できますが、<br>
Object は <strong>文字列キーしか使えず、順序も安定しません。</strong></p>
<div>
<input id="keyInput" placeholder="キー(例: 42 または [1,2])">
<input id="valueInput" placeholder="値(例: hello)">
<button id="addBtn">追加</button>
</div>
<div class="area">
<div class="panel" id="mapPanel">
<h2>🗺️ Map</h2>
<div id="mapList"></div>
</div>
<div class="panel" id="objectPanel">
<h2>🧱 Object</h2>
<div id="objList"></div>
</div>
</div>
<div class="msg" id="message"></div>
<div class="explain">
<h3>💡 見どころ</h3>
<ul>
<li><strong>Map</strong> はオブジェクトや数値をキーにできる。</li>
<li><strong>Object</strong> はキーを自動で文字列化してしまう(例: <code>[1,2]</code> → <code>"1,2"</code>)。</li>
<li>Map は<strong>追加順を保持</strong>するが、Object は保証されない。</li>
</ul>
</div>
<script>
const myMap = new Map();
const myObj = {};
const mapList = document.getElementById("mapList");
const objList = document.getElementById("objList");
const message = document.getElementById("message");
function renderMap() {
mapList.innerHTML = "";
for (const [k, v] of myMap.entries()) {
const div = document.createElement("div");
div.className = "pair";
div.innerHTML = `<span class="key">${JSON.stringify(k)}</span>
<span class="arrow">→</span>
<span class="value">${v}</span>`;
mapList.appendChild(div);
}
}
function renderObject() {
objList.innerHTML = "";
for (const k in myObj) {
const div = document.createElement("div");
div.className = "pair";
div.innerHTML = `<span class="key">"${k}"</span>
<span class="arrow">→</span>
<span class="value">${myObj[k]}</span>`;
objList.appendChild(div);
}
}
document.getElementById("addBtn").addEventListener("click", () => {
const keyText = document.getElementById("keyInput").value.trim();
const value = document.getElementById("valueInput").value.trim();
if (!keyText || !value) return;
let parsedKey;
try {
// try to evaluate as JS literal (e.g. 42, [1,2])
parsedKey = eval("(" + keyText + ")");
} catch {
parsedKey = keyText;
}
// Map への追加・更新
const exists = myMap.has(parsedKey);
myMap.set(parsedKey, value);
// Object はキーが文字列に変換される
const keyForObject = typeof parsedKey === "object" ? parsedKey.toString() : String(parsedKey);
myObj[keyForObject] = value;
renderMap();
renderObject();
// アニメーションハイライト
const mapPairs = mapList.querySelectorAll(".pair");
const objPairs = objList.querySelectorAll(".pair");
if (mapPairs.length) mapPairs[mapPairs.length - 1].classList.add("highlight");
if (objPairs.length) objPairs[objPairs.length - 1].classList.add("highlight");
if (exists) {
message.textContent = `🔄 Mapのキー「${keyText}」を更新しました(値: ${value})。`;
} else {
message.textContent = `✅ 「${keyText} → ${value}」を追加しました。`;
}
document.getElementById("keyInput").value = "";
document.getElementById("valueInput").value = "";
});
</script>
</body>
</html>
HTMLこのデモで学べること
| 比較項目 | 🗺️ Map | 🧱 Object |
|---|---|---|
| キーの型 | 何でもOK(数値・オブジェクト・関数など) | 自動で文字列化される |
| 順序の保持 | 追加順を保持する | 保証されない(ブラウザ実装依存) |
| サイズ取得 | .size プロパティで簡単 | Object.keys(obj).length が必要 |
| 繰り返し | for...of / .forEach() で簡単 | for...in / Object.keys() が必要 |
体験例
キー: 42,値: "answer"→ Map は数値キーOK
→ Object では"42"に変換されるキー: [1,2],値: "array"→ Object 側はキー"1,2"に…キー: "name",値: "Halu"→ 両方OK(ただし Map は追加順維持)


