まずざっくりイメージ:Map と Object は「役割」が違う
同じように「キーと値」を扱えるので、最初は
「Map でも Object でもできるじゃん。どっち使えばいいの?」
と感じると思います。
ざっくり分けると、こうです。
- Object:
「1人のユーザー」や「1つの商品」みたいな、
“1件のデータ(レコード)” を表すための入れ物 - Map:
「ユーザーID → ユーザー情報」みたいな、
“キーと値の集まり(辞書・マップ)” を扱うためのコレクション
つまり、
- 「1つのものの属性(id, name, age …)を持ちたい」 → Object
- 「たくさんのキーと値を、出し入れ・検索したい」 → Map
という意識を持つと、かなり整理されます。
基本的な使い方の違いをコードで見る
Object でキーと値
const user = {
id: 1,
name: "Alice",
age: 20,
};
// 取得
console.log(user.name); // Alice
console.log(user["age"]); // 20
// 追加
user.email = "alice@example.com";
// 削除
delete user.age;
JavaScriptObject は「その1人のユーザーの情報」を表すのに向いています。
プロパティ名は基本、文字列(かシンボル)です。
Map でキーと値
const userMap = new Map();
// 追加
userMap.set("id", 1);
userMap.set("name", "Alice");
// 取得
console.log(userMap.get("name")); // Alice
// 存在チェック
console.log(userMap.has("id")); // true
// 削除
userMap.delete("id");
// 要素数
console.log(userMap.size); // 1
JavaScriptぱっと見似ていますが、
- 「set / get / has / delete / size」という専用メソッド(プロパティ)で扱える
- キーにオブジェクトなども使える
- 挿入順でループできる
という点が大きく違います。
重要な違い1:キーに何を使えるか
Object のキーは基本「文字列」
const obj = {};
obj["123"] = "number key";
obj[123] = "also number key"; // 実際は "123" に変換される
console.log(obj["123"]); // also number key
console.log(obj[123]); // also number key(同じ)
JavaScript数値で書いても、内部的には文字列になります。
また、オブジェクトをキーにしても、結局 "[object Object]" などに文字列化されてしまいます。
const objKey = { id: 1 };
const obj = {};
obj[objKey] = "value";
console.log(obj); // { "[object Object]": "value" }
JavaScriptMap は「どんな値でも」キーにできる
const m = new Map();
const objKey = { id: 1 };
const arrKey = [1, 2, 3];
m.set(objKey, "オブジェクトに紐づく値");
m.set(arrKey, "配列に紐づく値");
m.set(123, "数値キー");
m.set(true, "真偽値キー");
console.log(m.get(objKey)); // オブジェクトに紐づく値
console.log(m.get(arrKey)); // 配列に紐づく値
JavaScriptここが非常に重要です。
- Object:
キーは「文字列かシンボル」。
オブジェクトをキーにする発想とは相性が悪い。 - Map:
キーは 何でも OK(オブジェクト・配列・関数もそのままキーになる)。
「このオブジェクトに対する付随情報を持ちたい」
「DOM 要素ごとに状態を持ちたい」
というような場面では、Map の方が圧倒的に自然です。
重要な違い2:サイズの取得・追加/削除のしやすさ
Object のサイズを数えるのはひと手間
Object に「いくつプロパティがあるか」を知るには、こんな書き方になります。
const obj = { a: 1, b: 2, c: 3 };
const size = Object.keys(obj).length;
console.log(size); // 3
JavaScript毎回 Object.keys(obj).length と書くのは、少しもっさりしています。
Map は size プロパティで一発
const m = new Map();
m.set("a", 1);
m.set("b", 2);
m.set("c", 3);
console.log(m.size); // 3
JavaScriptこの違いは、「辞書」としてガンガン要素を出し入れする場面で効いてきます。
また、存在チェックや削除も Map の方が素直です。
Object:
const obj = { a: 1 };
console.log("a" in obj); // true
delete obj.a;
JavaScriptMap:
const m = new Map();
m.set("a", 1);
console.log(m.has("a")); // true
m.delete("a");
JavaScriptここが重要です。
「増やす・減らす・存在チェック・サイズ確認」を頻繁にやるなら、Map の方が読みやすく、間違いにくい。
重要な違い3:ループと順序
Object のループ
Object をループするときは for...in か Object.keys/values/entries を使います。
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(key, obj[key]);
}
// a 1
// b 2
// c 3
JavaScript最近の仕様では「追加した順」がある程度守られますが、
歴史的には少しややこしい仕様があり、完全に「順序付きの辞書」として設計されているわけではありません。
Map のループは「挿入順」で安定している
const m = new Map();
m.set("a", 1);
m.set("b", 2);
m.set("c", 3);
for (const [key, value] of m) {
console.log(key, value);
}
// a 1
// b 2
// c 3
JavaScriptfor...of で回すと [key, value] のペアが順番に出てきます。keys(), values(), entries() も使えます。
for (const key of m.keys()) {
console.log("key:", key);
}
for (const value of m.values()) {
console.log("value:", value);
}
JavaScriptMap は「順序付きのキー集合」として明確に設計されています。
順番に意味がある「設定の一覧」「ミドルウェアの登録順」などには Map の方が安心して使えます。
重要な違い4:プロトタイプ汚染・特別なキーを気にしなくてよい
Object はプロトタイプを持つ
Object は Object.prototype を継承しているので、toString や hasOwnProperty など、最初からいくつかのプロパティを持っています。
const obj = {};
console.log("toString" in obj); // true
JavaScriptつまり、ユーザーが "toString" というキーを使うとき、
微妙に気をつける必要があったりします(最近は Object.create(null) を使うなどのテクニックもありますが、初心者には少し遠い話)。
Map には「余計なプロパティ」がない
Map は純粋に「キー → 値」を扱うための専用コレクションです。toString のような紛らわしいプロパティは、最初から存在しません。
const m = new Map();
console.log(m.has("toString")); // false
JavaScriptここが重要です。
Object は「JS の基礎構造」としての歴史的な事情が多い。
Map は「キーと値の辞書」のために設計された、より素直なデータ構造。
「辞書としてだけ見たい」なら、多くの場合 Map の方が考えることが少なくて済みます。
何をするときに Object、何をするときに Map?
Object が向いている場面
Object は、「1件のデータ」「固定された項目」を扱うときに向いています。
例えば、ユーザー情報:
const user = {
id: 1,
name: "Alice",
age: 20,
};
JavaScriptJSON でやり取りするデータは基本的に Object ですし、
クラスのインスタンスのプロパティも Object の世界です。
「このユーザーが何者か」を表現する単位として、Object はとても自然です。
Map が向いている場面
Map は、「たくさんのキーと値のペア」を扱うときに向いています。
例えば:
ユーザーID → ユーザーオブジェクト
キャッシュキー → 計算結果
DOM 要素 → 追加情報
など、「キー集合」としての性格が強いものです。
例:ユーザーID → ユーザーのマップ
const users = new Map();
users.set(1, { id: 1, name: "Alice" });
users.set(2, { id: 2, name: "Bob" });
console.log(users.get(1)); // { id: 1, name: "Alice" }
JavaScript例:DOM 要素 → イベント用の補助情報
const elementState = new Map();
function setState(el, state) {
elementState.set(el, state);
}
function getState(el) {
return elementState.get(el);
}
JavaScriptよくある「間違った使い方」
よくあるパターンとして、
- 「全部の設定を 1 つの Object に突っ込んで、あとからどんどん増やす」
- 「キーの数を数える」「削除を頻繁にやる」のに Object を辞書として使い続ける
というのがあります。
そういうときは、
「これ、本当は “1件のデータ” じゃなくて、“キーと値の集合” を扱いたいんじゃない?」
と自分に問いかけてみてください。
答えが Yes なら、Map を使うとコードが一気にスッキリする可能性が高いです。
具体例で「Map と Object の役割分担」を体感する
例1:Object で「1件のユーザー」、Map で「ユーザー一覧」
// 1人のユーザー(Object が自然)
const user1 = {
id: 1,
name: "Alice",
};
const user2 = {
id: 2,
name: "Bob",
};
// ユーザーID → ユーザーのマップ(Map が自然)
const userMap = new Map();
userMap.set(user1.id, user1);
userMap.set(user2.id, user2);
console.log(userMap.get(1)); // user1
console.log(userMap.get(2)); // user2
JavaScript「個々のユーザー」には Object、
「それらの一覧・辞書」として Map、という分担がキレイです。
例2:頻度カウンター(Map のほうが素直)
文字列中の文字の出現回数を数える例です。
Object で書くと:
function countCharsObj(str) {
const counter = {};
for (const ch of str) {
if (counter[ch] === undefined) {
counter[ch] = 0;
}
counter[ch]++;
}
return counter;
}
console.log(countCharsObj("hello"));
// { h: 1, e: 1, l: 2, o: 1 }
JavaScriptMap で書くと:
function countCharsMap(str) {
const counter = new Map();
for (const ch of str) {
const count = counter.get(ch) || 0;
counter.set(ch, count + 1);
}
return counter;
}
const result = countCharsMap("hello");
for (const [ch, count] of result) {
console.log(ch, count);
}
// h 1
// e 1
// l 2
// o 1
JavaScriptどちらも書けますが、Map の get / set の方が「辞書を扱っている」という意図が伝わりやすいです。
例3:キーにオブジェクトや DOM を使う(Map の独壇場)
const button1 = document.createElement("button");
const button2 = document.createElement("button");
const clickCount = new Map();
function registerClickCount(button) {
clickCount.set(button, 0);
button.addEventListener("click", () => {
const current = clickCount.get(button) ?? 0;
clickCount.set(button, current + 1);
console.log("クリック回数:", clickCount.get(button));
});
}
registerClickCount(button1);
registerClickCount(button2);
JavaScriptここで Object を使うのは現実的ではありません。button 自体をキーにできる、という Map の性質が効いています。
まとめ:Map vs Object の「考え方の軸」
最後に、実際に選ぶときの軸を言い切ります。
- 「1件のデータ(レコード)を表したいか?」
→ Yes なら Object - 「キーと値の集まり(辞書)を扱いたいか?」
→ Yes なら Map - 「キーにオブジェクトや DOM 要素を使いたいか?」
→ Yes なら絶対に Map - 「頻繁に追加・削除・存在チェック・サイズ確認をするか?」
→ Yes なら Map のほうが素直で安全 - 「JSON にしたい」「API レスポンスをそのまま扱いたい」
→ 基本 Object の世界
ここが重要です。
どちらでも「技術的には」できる場合でも、「意味としてどちらがしっくりくるか」を優先する。
「これは 1人のユーザーのデータだから Object」
「これはユーザーの一覧で、ID から検索したいから Map」
と、自分の中で筋が通っていると、コードの読みやすさが大きく変わります。
まずは、自分のコードの中で「辞書っぽい Object」を一つ見つけて、
それを Map に書き換えてみてください。
どこが楽になるか、どんなときに Map が気持ちいいかが、
体感でつかめてきます。
