Map とは何か(まずイメージから)
Map は、ES6 で追加された
「キーと値のペアを柔軟に保存できる専用のコレクション」 です。
似たものに「オブジェクト {}」がありますが、Map には大きな違いがあります。
- オブジェクト
- キーは基本「文字列 or シンボル」
- プロトタイプの影響を受ける
- Map
- キーに「どんな値でも」使える(オブジェクト、配列、関数など)
- 挿入した順番を保つ
- サイズを簡単に取得できる
まずはざっくり使い方を見てみます。
const m = new Map();
// 追加
m.set("name", "Alice");
m.set("age", 20);
// 取得
console.log(m.get("name")); // Alice
// 存在チェック
console.log(m.has("age")); // true
// 削除
m.delete("age");
// 要素数
console.log(m.size); // 1
JavaScriptここが重要です。
Map は「キーと値」を扱う点ではオブジェクトと似ているが、「キーとして使える範囲」と「動作の素直さ」がかなり違う専用コレクション です。
特に「オブジェクトをキーにしたい」時は Map 一択です。
Map の基本操作(set / get / has / delete)
Map の作り方と set での追加
const userMap = new Map();
userMap.set("id", 1);
userMap.set("name", "Alice");
console.log(userMap);
// Map(2) { 'id' => 1, 'name' => 'Alice' }
JavaScriptset(key, value) でキーと値のペアを追加します。
同じキーに再度 set すると、上書きになります。
userMap.set("name", "Bob");
console.log(userMap.get("name")); // Bob
JavaScriptget で取得、has で存在チェック
console.log(userMap.get("id")); // 1
console.log(userMap.get("age")); // 存在しない → undefined
console.log(userMap.has("id")); // true
console.log(userMap.has("age")); // false
JavaScriptget は存在しないキーに対して undefined を返します。
「キーがあるかどうか」を知りたいときは has を使うと安全です。
delete と clear で削除
userMap.delete("id"); // 指定キーを削除
console.log(userMap.has("id")); // false
userMap.clear(); // 全削除
console.log(userMap.size); // 0
JavaScriptsize プロパティで要素数が一発で分かる
const m = new Map();
m.set("a", 1);
m.set("b", 2);
console.log(m.size); // 2
JavaScriptオブジェクト {} の場合、プロパティ数を数えるには Object.keys(obj).length のような書き方が必要でしたが、
Map は size で即座に分かります。
ここが重要です。
「キーの追加、削除、個数確認」を頻繁にやるなら、オブジェクトより Map の方が素直で扱いやすい です。
オブジェクトとの大きな違い(ここを深掘り)
違い1:キーに「何でも」使える(オブジェクトも配列も)
オブジェクト {} ではキーは文字列(とシンボル)だけですが、
Map では オブジェクト自体をキーにできます。
const m = new Map();
const objKey = { id: 1 };
const arrKey = [1, 2, 3];
m.set(objKey, "オブジェクトに紐づく値");
m.set(arrKey, "配列に紐づく値");
console.log(m.get(objKey)); // オブジェクトに紐づく値
console.log(m.get(arrKey)); // 配列に紐づく値
JavaScriptID → ユーザー情報、という形ではなく、ユーザーオブジェクト → 関連データ のように「そのもの」をキーにしたいときに非常に便利です。
ここが重要です。
「オブジェクトをキーにしたい」= 普通のオブジェクトではほぼ無理(プロパティ名に文字列化されてしまう)
→ Map ならそのままキーとして扱える。
違い2:挿入順序を保持してくれる
Map は、
「キーを追加した順番」のままループできます。
const m = new Map();
m.set("first", 1);
m.set("second", 2);
m.set("third", 3);
for (const [key, value] of m) {
console.log(key, value);
}
// first 1
// second 2
// third 3
JavaScriptオブジェクトも最近の仕様ではある程度順序が保たれますが、
Map は「順序付きのキー集合」として公式に設計されています。
違い3:プロトタイプや特別なキーに悩まされない
オブジェクト {} には、toString などのプロトタイプから継承したプロパティがあります。
const obj = {};
console.log("toString" in obj); // true
JavaScriptMap は純粋な「キー → 値」のコレクションなので、toString のような紛らわしいキーは最初から存在しません。
const m = new Map();
console.log(m.has("toString")); // false
JavaScriptオブジェクトでキーを扱うときにややこしい「特別扱いのプロパティ」に悩まされないのは、Map の大きな利点です。
Map のイテレーション(for…of / keys / values / entries)
Map 自体を for…of すると [key, value] のペアになる
const m = new Map();
m.set("name", "Alice");
m.set("age", 20);
for (const [key, value] of m) {
console.log(key, value);
}
// name Alice
// age 20
JavaScript分割代入 [key, value] がとても相性よく使えます。
keys / values / entries でそれぞれ取り出す
const m = new Map();
m.set("a", 1);
m.set("b", 2);
for (const key of m.keys()) {
console.log("key:", key);
}
for (const value of m.values()) {
console.log("value:", value);
}
for (const [key, value] of m.entries()) {
console.log(key, value);
}
JavaScriptm と m.entries() は同じ動き([key, value] ペア)をします。
forEach も使える
m.forEach((value, key) => {
console.log(key, value);
});
JavaScriptコールバックの引数の順番が (value, key) であることに注意してください。
(オブジェクトの Array.prototype.forEach と同じ順序です)
よくある用途と具体例
例1:オブジェクトをキーにして追加情報を持たせる
const user1 = { id: 1, name: "Alice" };
const user2 = { id: 2, name: "Bob" };
const extraInfo = new Map();
extraInfo.set(user1, { lastLogin: "2025-01-01" });
extraInfo.set(user2, { lastLogin: "2025-01-05" });
console.log(extraInfo.get(user1)); // { lastLogin: "2025-01-01" }
JavaScriptuser1 や user2 に直接プロパティを追加しても良いですが、
「元のオブジェクトは触りたくない」「外から渡されたオブジェクトに対して付加情報を持ちたい」
といった場面で Map が役立ちます。
例2:頻度カウンター(出現回数を数える)
文字列中の各文字が何回出てくるかを数える例です。
function countChars(str) {
const map = new Map();
for (const ch of str) {
const count = map.get(ch) || 0;
map.set(ch, count + 1);
}
return map;
}
const result = countChars("hello");
for (const [ch, count] of result) {
console.log(ch, count);
}
// h 1
// e 1
// l 2
// o 1
JavaScriptここが重要です。
「キーの存在チェック → 無ければ 0 から → 1 足す」
という処理をするとき、has / get / set が非常に素直に使えます。
オブジェクトでも書けますが、Map の方が「辞書」操作っぽくて読みやすいです。
例3:順番が重要な設定の管理
例えば、ミドルウェアのように「追加順に処理したい」場合。
const middlewares = new Map();
middlewares.set("auth", (req) => { console.log("認証処理"); });
middlewares.set("logging", (req) => { console.log("ログ処理"); });
function handleRequest(req) {
for (const [name, fn] of middlewares) {
console.log(`--- ${name} ---`);
fn(req);
}
}
handleRequest({});
// --- auth ---
// 認証処理
// --- logging ---
// ログ処理
JavaScript追加順序が保証されるので、「登録した順に実行する」というロジックが自然に書けます。
オブジェクトと Map をどう使い分けるか
オブジェクト向きの場面
オブジェクト {} は、主に「固定された構造のデータ」に向いています。
- ユーザー1人の情報(id, name, age など)
- API から返ってくる JSON
- クラスのインスタンスのプロパティ
const user = {
id: 1,
name: "Alice",
age: 20,
};
JavaScript「キーの種類があらかじめ決まっていて、増えたり減ったりしない」ようなデータです。
Map 向きの場面
Map は、主に「可変なキー集合」「辞書・マップ」として使うのに向いています。
- 任意のキー(特にオブジェクト)を使いたい
- 要素を頻繁に追加・削除する
- キーの数を簡単に知りたい
- 挿入順序に意味がある
const cache = new Map();
cache.set("user:1", { id: 1, name: "Alice" });
cache.set("user:2", { id: 2, name: "Bob" });
JavaScriptここが重要です。
「構造化された1件のデータ」→ オブジェクト
「キーと値の集まり(辞書・マップ)」→ Map
という大まかな切り分けを頭に置いておくと、かなり選びやすくなります。
Map の初期化と便利テク
二次元配列から初期化
Map は、[キー, 値] のペアの配列から作ることができます。
const m = new Map([
["apple", 100],
["banana", 150],
["orange", 120],
]);
console.log(m.get("banana")); // 150
JavaScriptCSV や JSON など外部データから Map を作るときに便利です。
Map から配列へ変換
逆に、Map を配列に変換するのも簡単です。
const arr = [...m]; // [[key, value], [key, value], ...]
console.log(arr);
const keys = [...m.keys()];
const values = [...m.values()];
JavaScriptArray.from(m) でも同じように配列化できます。
まとめ
Map の核心は、
「キーに何でも使えて、順序付きで、操作が素直な“辞書”のようなコレクション」 であることです。
押さえておきたいポイントを整理すると:
set,get,has,delete,clear,sizeが基本操作- キーにオブジェクト・配列・関数など何でも使える
- 挿入順序を保ち、
for...ofやkeys,values,entries,forEachで走査できる - オブジェクト
{}は「1件の構造化データ」に、Map は「キーと値の可変な集まり」に向いている - 頻度カウンタ、オブジェクトをキーにした追加情報、順序付き設定などで特に威力を発揮する
まずは、オブジェクトで書いていた「辞書」のような処理を、
一度 Map に書き換えてみてください。
「キー存在チェック → 追加・更新 → ループ」の流れが、
Map だとどれだけ素直に書けるかが、実感として分かってくるはずです。

