面試???js中 Map和 Object 的區(qū)別小結(jié)
Map 和 Object 都是用于存儲(chǔ)鍵值對的數(shù)據(jù)結(jié)構(gòu),但它們之間存在許多關(guān)鍵區(qū)別。
簡單來說,Map 是一個(gè)更專門化、功能更強(qiáng)大的鍵值對集合,而 Object 則是一個(gè)更通用的、用于描述實(shí)體的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。
下面我們從多個(gè)維度來詳細(xì)對比它們的區(qū)別。
核心區(qū)別對比表
| 特性 | Map | Object |
|---|---|---|
| 鍵的類型 | 任意類型(函數(shù)、對象、基本類型等) | 只能是 String 或 Symbol(其他類型會(huì)被自動(dòng)轉(zhuǎn)換為字符串) |
| 鍵的順序 | 鍵值對保持插入時(shí)的順序 | ES6后: String鍵按創(chuàng)建順序;Symbol鍵無固定順序。 ES6前: 順序無保證,因引擎而異。 |
| 大小獲取 | 通過 size 屬性輕松獲取:map.size | 需要手動(dòng)計(jì)算:Object.keys(obj).length |
| 迭代 | 可直接迭代(是 Iterable 對象),支持 for...of,直接提供 .keys(), .values(), .entries() 方法 | 默認(rèn)不可直接迭代。需要先獲取鍵數(shù)組(如Object.keys(obj)),或使用 for...in(會(huì)遍歷原型鏈上的可枚舉屬性)。 |
| 默認(rèn)屬性 | 純凈,不包含任何默認(rèn)的鍵值對 | 有原型,可能包含從原型鏈繼承來的屬性(如toString, constructor),可能干擾鍵的訪問。 |
| 性能 | 在頻繁增刪鍵值對的場景下性能更優(yōu) | 在頻繁增刪鍵值對的場景下性能稍差(但具體場景需測試) |
| 序列化 | 默認(rèn)沒有原生的JSON序列化支持 | 完美支持 JSON.stringify 和 JSON.parse |
詳細(xì)解釋與示例
1. 鍵的類型 (Key Type)
這是最根本的區(qū)別。
Object 的鍵只能是 String 或 Symbol。如果你使用一個(gè)非字符串的鍵(如一個(gè)對象),它會(huì)被自動(dòng)通過 .toString() 方法轉(zhuǎn)換為字符串。
const obj = {};
const key = { id: 1 };
obj[key] = 'value'; // key 被轉(zhuǎn)換為字符串 "[object Object]"
console.log(obj); // { "[object Object]": "value" }
// 現(xiàn)在你無法再用 key 對象來訪問這個(gè)值,因?yàn)樵L問時(shí)又會(huì)轉(zhuǎn)換為相同的字符串
Map 的鍵可以是任何數(shù)據(jù)類型,包括對象、函數(shù)、NaN等。它使用“SameValueZero”算法來判斷鍵的相等性(類似于 ===,但認(rèn)為 NaN === NaN)。
const map = new Map();
const key = { id: 1 };
map.set(key, 'value');
map.set(NaN, 'This is NaN');
map.set(() => {}, 'A function as key');
console.log(map.get(key)); // 'value'
console.log(map.get(NaN)); // 'This is NaN'
// 鍵是唯一的,不會(huì)發(fā)生轉(zhuǎn)換
2. 順序 (Order)
- Map 會(huì)嚴(yán)格按照鍵值對的插入順序來記錄和迭代它們。
- Object 的順序在 ES6 之前沒有明確定義。從 ES6 開始,規(guī)范規(guī)定了:
- String 類型的鍵會(huì)按照創(chuàng)建的順序記錄。
- Symbol 類型的鍵則沒有固定的順序。
- 但為了兼容性,最好不要依賴 Object 的屬性順序。
3. 迭代 (Iteration)
Map 是一個(gè)可迭代對象(實(shí)現(xiàn)了 Symbol.iterator),這意味著你可以直接用它來進(jìn)行 for...of 循環(huán),或者使用展開運(yùn)算符 ... 將其轉(zhuǎn)換為數(shù)組。
const map = new Map([['a', 1], ['b', 2]]);
for (const [key, value] of map) {
console.log(key, value);
}
// Output: a 1, b 2
console.log([...map]); // [ ['a', 1], ['b', 2] ]
Object 默認(rèn)不可直接迭代。你需要使用 Object.keys(), Object.values(), 或 Object.entries() 先獲取一個(gè)數(shù)組,然后再迭代這個(gè)數(shù)組。
const obj = { a: 1, b: 2 };
for (const key of Object.keys(obj)) {
console.log(key, obj[key]);
}
4. 大小 (Size)
Map 的大小可以通過 size 屬性輕松、高效地獲取。
console.log(map.size); // 2
Object 的大小需要通過 Object.keys(obj).length 來計(jì)算,這在性能敏感的場景下可能稍慢。
console.log(Object.keys(obj).length); // 2
5. 原型和默認(rèn)鍵 (Prototype and Default Keys)
Object 可能受到原型鏈上的屬性污染。如果你不小心,可能會(huì)覆蓋或訪問到繼承來的方法(如 hasOwnProperty)。你需要使用 obj.hasOwnProperty('key') 來檢查一個(gè)屬性是否是自身的。
const obj = {};
console.log('toString' in obj); // true,因?yàn)閺脑玩溊^承而來
Map 是“純凈”的,它只包含你顯式放入的鍵值對,沒有任何默認(rèn)的鍵,因此更安全。
const map = new Map();
console.log(map.has('toString')); // false
6. 序列化和解析 (Serialization and Parsing)
Object 可以無縫地與 JSON 格式相互轉(zhuǎn)換。
const obj = { a: 1 };
const str = JSON.stringify(obj); // '{"a":1}'
const newObj = JSON.parse(str); // { a: 1 }
Map 默認(rèn)無法被 JSON.stringify 正確處理,會(huì)序列化為一個(gè)空對象 {}。你需要自己編寫轉(zhuǎn)換邏輯。
const map = new Map([['a', 1]]);
const str = JSON.stringify(map); // '{}'
// 轉(zhuǎn)換 Map -> JSON
const mapToJson = (map) => JSON.stringify([...map]);
// 轉(zhuǎn)換 JSON -> Map
const jsonToMap = (jsonStr) => new Map(JSON.parse(jsonStr));
何時(shí)使用 Map vs Object?
使用Map的場景:
- 鍵的類型未知或多樣:當(dāng)你需要使用非字符串/符號作為鍵時(shí)(如 DOM 節(jié)點(diǎn)、對象等)。
- 需要維護(hù)插入順序:并且需要依賴這個(gè)順序進(jìn)行迭代或其他操作。
- 頻繁地添加和刪除鍵值對:
Map在頻繁更新的場景下性能優(yōu)化得更好。 - 需要避免與原型上的鍵產(chǎn)生沖突:需要一個(gè)純凈的鍵值對集合時(shí)。
使用Object的場景:
- 處理 JSON 數(shù)據(jù):需要頻繁地進(jìn)行序列化和反序列化。
- 結(jié)構(gòu)是固定的:你需要一個(gè)“實(shí)體”來描述某個(gè)事物,其屬性和方法在開發(fā)時(shí)就是已知的(例如,
user = { name: 'John', age: 30 })。 - 需要用到“方法”:對象可以包含函數(shù)(方法),而 Map 的值雖然也可以是函數(shù),但語法上不如對象的方法直觀(
obj.method()vsmap.get('method')())。 - 使用簡單的字符串鍵:并且不需要
Map提供的那些高級特性(如順序、任意鍵類型等)。
總結(jié)
| 如果你需要… | 那么選擇… |
|---|---|
| 存儲(chǔ)任意類型的鍵 | Map |
| 保證鍵值對的插入順序 | Map |
| 頻繁地添加/刪除元素 | Map |
| 純凈的、無原型干擾的集合 | Map |
| 簡單的結(jié)構(gòu),已知的字符串鍵 | Object |
| 與 JSON 無縫交互 | Object |
| 包含方法(函數(shù)) | Object |
在現(xiàn)代 JavaScript 開發(fā)中,當(dāng)你的需求更偏向于一個(gè)純粹的“鍵值對集合”或“哈希映射”時(shí),Map 通常是比 Object 更優(yōu)的選擇。
到此這篇關(guān)于s中 Map和 Object 的區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)js Map和Object區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JavaScript中利用Array和Object實(shí)現(xiàn)Map的方法
- Springboot通過ObjectMapper配置json序列化詳解
- 使用ObjectMapper把Json轉(zhuǎn)換為復(fù)雜的實(shí)體類
- JavaScript中Object、map、weakmap的區(qū)別分析
- JavaScript 中有了Object 為什么還需要 Map 呢
- JavaScript?Map?和?Object?的區(qū)別解析
- JavaScript中Map與Object應(yīng)用場景
- JS中Map、WeakMap和Object的區(qū)別解析
- Javascript中Object和Map之間的轉(zhuǎn)換方法
相關(guān)文章
webstorm調(diào)試uniapp程序的簡單步驟記錄
這篇文章主要給大家介紹了關(guān)于webstorm調(diào)試uniapp程序的簡單步驟,文中通過圖文介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用webstorm具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-12-12
微信小程序?qū)崿F(xiàn)卡片左右滑動(dòng)效果的示例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)卡片左右滑動(dòng)效果的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
JavaScript實(shí)現(xiàn)頁面無操作倒計(jì)時(shí)退出
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)頁面無操作倒計(jì)時(shí)退出,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10

