解説
Mapなら1と文字列の1を別に持てる?Objectとのキーの違いを試そう
Mapの数値・文字列・オブジェクトキーを比較。普通のObjectの文字列キーへの変換、同じ参照による上書きとgetの結果を確認。

識別用の値をキーにして対応表を作ったら、数値1の登録が文字列'1'で上書きされた。普通のObjectとMapでは、キーに使える値の扱いが違うよ。
このページは、オブジェクトと変数の基本を知っている人向け。固定の架空データを使い、何をキーとして同じと見なすかを確認する。保存や外部通信はしないブラウザ作例だよ。
普通のObjectでは、キーは文字列かSymbol
const table = {};
table[1] = '数値で登録';
table['1'] = '文字列で登録';
console.log(Object.keys(table)); // ['1']
console.log(table[1]); // '文字列で登録'
普通のObjectのプロパティのキーは文字列かSymbol。ここでは数値1を角括弧で渡しても、文字列'1'というキーとして扱うため、二回目の代入で同じ項目を上書きする。
これは1と'1'がJavaScriptのあらゆる比較で同じ、という意味ではないよ。Objectのプロパティへアクセスするときのキーの変換を見ているんだ。
Mapは、数値と文字列を別のキーにできる
const table = new Map();
table.set(1, '数値で登録');
table.set('1', '文字列で登録');
console.log(table.size); // 2
console.log(table.get(1)); // '数値で登録'
console.log(table.get('1')); // '文字列で登録'
Mapはキーと値の対応を保存するためのオブジェクト。setで登録し、getで取り出す。この例では数値1と文字列'1'を別のキーとして保持するので、要素数のsizeは2になる。
table[1]というプロパティをMapへ付けても、set(1, ...)と同じ登録にはならない。Mapの中身を扱うときは、set・get・has・deleteなどのメソッドを使い分けよう。
オブジェクトの中身ではなく参照を見る
const key = { id: 1 };
const table = new Map([[key, '登録済み']]);
console.log(table.get(key)); // '登録済み'
console.log(table.has({ id: 1 })); // false
Mapのオブジェクトキーは、同じ参照かで区別される。新しく書いた{id:1}は、内容が似ていても別のオブジェクトなので、元のkeyとして見つからないよ。
同じkeyでsetをもう一度呼ぶと、別の行を追加するのではなく、そのキーの値を更新する。逆に、別々に作った二つの{id:1}をキーにすれば、二つの対応として残る。
三つのモードで対応を確認する
作例では、数値1と文字列'1'、同じオブジェクトを二回、同じidを持つ別のオブジェクトという三つを切り替える。
| 入力するキー | Mapのsize | 結果の見方 |
|---|---|---|
| 数値1、文字列'1' | 2 | 型を分けて保持 |
| 同じオブジェクトを二回 | 1 | 後の値へ更新 |
| 別の{id:1}を一つずつ | 2 | 二つの参照を保持 |
表示されたJSONだけでは、オブジェクトの参照の違いは分からない。作例には、先頭二つのキーが===で同じかも併記している。「最初から試す」で数値と文字列の例へ戻せるよ。
データのIDでまとめたいなら、設計が別に必要
idが同じ記録を一つにする業務上の目的なら、レコードのオブジェクト自体をキーにするのか、idの値をキーにするのかを決めよう。同じidで内容が違うときに上書きしてよいかも、Mapが勝手に判断するわけではない。
また、MapをJSONへ保存すればキーの型が自動で元どおり戻る、とも考えないでね。保存形式と読み戻し方は別に決める必要がある。ここではブラウザ内の一時的な対応に絞っているよ。
動かしてみよう:Map / Object の対応表
設定や入力を切り替え、実際の表示と結果を比べよう。リセットで初期状態へ戻せるよ。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。