為什么說 JavaScript Map 比對象更香?
傳統(tǒng)上,存儲鍵值對的數(shù)據(jù)結(jié)構(gòu)時,對象 (Object) 一直是我們的首選。然而,ES6 引入了 Map 對象,它提供了一種更強(qiáng)大、更靈活的方式來處理鍵值對。以前也懶得用,直到最近用了下,我發(fā)現(xiàn) Map 比對象更香。
1. 鍵的類型不再局限
這是 Map 最顯著的優(yōu)勢之一。對象只能使用字符串或 Symbol 作為鍵,這限制了其適用性。Map 則不同,可以使用任何數(shù)據(jù)類型作為鍵,包括對象、函數(shù)、數(shù)字,甚至 NaN。想象一下,你想要使用 DOM 元素作為鍵來存儲與其相關(guān)的數(shù)據(jù),Map 可以輕松實現(xiàn):
對象則無法實現(xiàn)這種靈活的鍵類型。
2. 鍵的順序得到保留
對象的屬性在添加時,其順序是不確定的,尤其是在較舊的 JavaScript 引擎中。雖然現(xiàn)代 JavaScript 引擎嘗試保留屬性的插入順序,但這種行為并非總是可靠的。Map 則不同,Map 對象會按照鍵值對插入的順序進(jìn)行存儲和迭代。這在需要維護(hù)特定順序的場景下非常有用:
3. 輕松獲取大小
要獲取對象中屬性的數(shù)量,你需要手動遍歷或者使用 Object.keys(obj).length,這既不優(yōu)雅,也可能效率不高。Map 對象提供了一個簡單的 size 屬性,可以直接獲取鍵值對的數(shù)量:
4. 避免原型鏈污染
JavaScript 對象會繼承原型鏈上的屬性。這意味著,如果不小心,你可能會意外訪問到原型鏈上的屬性,或者更糟糕的是,修改原型鏈上的屬性,導(dǎo)致全局污染。Map 對象不會繼承任何屬性,它完全隔離于原型鏈,更加安全可靠。
5. 更優(yōu)的性能
在某些場景下,特別是需要頻繁添加、刪除鍵值對的情況下,Map 對象通常比對象具有更好的性能。JavaScript 引擎對 Map 對象進(jìn)行了專門的優(yōu)化,使其更適合處理動態(tài)數(shù)據(jù)。
6. 內(nèi)置的迭代方法
Map 對象提供了內(nèi)置的迭代方法,例如 forEach、keys、values 和 entries,使得迭代鍵值對變得非常方便:
const myMap = new Map();
myMap.set('a', 1);
myMap.set('b', 2);
myMap.forEach((value, key) => {
console.log(key, value); // 輸出: a 1, b 2
});
for (const key of myMap.keys()) {
console.log(key); // 輸出: a, b
}
for (const value of myMap.values()) {
console.log(value); // 輸出: 1, 2
}
for (const [key, value] of myMap.entries()) {
console.log(key, value); // 輸出: a 1, b 2
}
何時仍然使用對象?
- 雖然 Map 在很多方面都優(yōu)于對象,但對象仍然有其用武之地。
- JSON: JSON 數(shù)據(jù)格式本質(zhì)上是對象。
- 簡單的配置對象: 對于簡單的、靜態(tài)的配置對象,對象仍然是一個不錯的選擇。
需要直接訪問屬性的情況: 如果需要使用 obj.propertyName 語法直接訪問屬性,對象仍然是必要的。但是,請注意,這可以通過將 Map 轉(zhuǎn)換為對象來實現(xiàn),但需要權(quán)衡性能。