JavaScript | 実際に Map / Set を操作するデモ

JavaScript
スポンサーリンク

ここでは、「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() が必要

体験例

  1. キー: 42, 値: "answer" → Map は数値キーOK
    → Object では "42" に変換される
  2. キー: [1,2], 値: "array" → Object 側はキー "1,2" に…
  3. キー: "name", 値: "Halu" → 両方OK(ただし Map は追加順維持)
タイトルとURLをコピーしました