どちらもキーバリューで管理できますが使い分けについて調べたり考えてみたので記載。
Map
・キーにString、シンボル以外も使える
・iterableである
・プロトタイプチェーンによるプロパティはない
const mp = new Map();
mp.set("hoge", "hogeValue");
mp.set(1, "one");
mp.set(true, true);
mp.forEach((v, k) => {
console.log(k); // hoge, 1, true
console.log(v); // hogeValue, one, true
});
// こういうふうにロジックを入れることも可能
mp.set("fn", () => console.log("execute"));
mp.get("fn")(); // execute
もちろんtypescriptであれば下記のように型定義もできます
const mp = new Map<string, string>();
mp.set(1, "one"); // エラー. Argument of type 'number' is not assignable to parameter of type 'string'.
object(インデックスシグネチャ)
・キーにstring, シンボルしか使えない
・iterableでない
・プロトタイプチェーンによるプロパティが存在する
const obj = {
hoge: 'hogeValue',
1: 'one',
}
// objectでイテレートしたい場合は下記のように
Object.entries(obj).forEach(([k, v]) => {
console.log(k); // hoge, 1
console.log(v); // hogeValue, one
});
どっちが良いん?
基本的にはMapを使っていくべきと感じました。
ただ、私は一意なキーバリューを定数として定義し、区分値の変換として使うことが多く、その際はobjectを使うとエラー出してくれるので重宝しています。
(プログラムミスによる定義重複を検出できます)
すみません、Javascriptだと後勝ちとなるようです。。。普段Typescriptでしか書いてないので気づきませんでした。。。
Typescriptだとtscやlinterでエラーとしてくれるので、この書き方をよくしています。
TypescriptはEnumあるじゃん!という意見もあると思うのでEnumではなくobjectを使う理由は別途まとめようと思います(ググるといっぱい出てくるけど。。。)
const STATUS_OBJ = {
success: "成功",
warn: "警告",
success: "成功2", // エラー. An object literal cannot have multiple properties with the same name.
}
const STATUS_MAP = new Map(
[
["success", "成功"],
["warn", "警告"],
["success", "成功2"] // エラー出てほしいけど出ない。後から定義されたもので上書きされる
]
);
以上です。他の視点があれば教えてください。