javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > js Map和Object区别

面试常考:js中 Map和 Object 的区别小结

作者:Bling_Bling_1

Map和Object都是键值对存储结构,但存在显著差异,本文就来介绍一下js中 Map和 Object 的区别小结,具有一定的参考价值,感兴趣的可以了解一下

MapObject 都是用于存储键值对的数据结构,但它们之间存在许多关键区别。

简单来说,Map 是一个更专门化、功能更强大的键值对集合,而 Object 则是一个更通用的、用于描述实体的基础数据结构。

下面我们从多个维度来详细对比它们的区别。

核心区别对比表

特性MapObject
键的类型任意类型(函数、对象、基本类型等)只能是 String 或 Symbol(其他类型会被自动转换为字符串)
键的顺序键值对保持插入时的顺序ES6后: String键按创建顺序;Symbol键无固定顺序。
ES6前: 顺序无保证,因引擎而异。
大小获取通过 size 属性轻松获取:map.size需要手动计算:Object.keys(obj).length
迭代可直接迭代(是 Iterable 对象),支持 for...of,直接提供 .keys(), .values(), .entries() 方法默认不可直接迭代。需要先获取键数组(如Object.keys(obj)),或使用 for...in(会遍历原型链上的可枚举属性)。
默认属性纯净,不包含任何默认的键值对有原型,可能包含从原型链继承来的属性(如toString, constructor),可能干扰键的访问。
性能在频繁增删键值对的场景下性能更优在频繁增删键值对的场景下性能稍差(但具体场景需测试)
序列化默认没有原生的JSON序列化支持完美支持 JSON.stringify 和 JSON.parse

详细解释与示例

1. 键的类型 (Key Type)

这是最根本的区别。

Object 的键只能是 StringSymbol。如果你使用一个非字符串的键(如一个对象),它会被自动通过 .toString() 方法转换为字符串。

const obj = {};
const key = { id: 1 };

obj[key] = 'value'; // key 被转换为字符串 "[object Object]"
console.log(obj); // { "[object Object]": "value" }
// 现在你无法再用 key 对象来访问这个值,因为访问时又会转换为相同的字符串

Map 的键可以是任何数据类型,包括对象、函数、NaN等。它使用“SameValueZero”算法来判断键的相等性(类似于 ===,但认为 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'
// 键是唯一的,不会发生转换

2. 顺序 (Order)

3. 迭代 (Iteration)

Map 是一个可迭代对象(实现了 Symbol.iterator),这意味着你可以直接用它来进行 for...of 循环,或者使用展开运算符 ... 将其转换为数组。

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 默认不可直接迭代。你需要使用 Object.keys(), Object.values(), 或 Object.entries() 先获取一个数组,然后再迭代这个数组。

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 来计算,这在性能敏感的场景下可能稍慢。

console.log(Object.keys(obj).length); // 2

5. 原型和默认键 (Prototype and Default Keys)

Object 可能受到原型链上的属性污染。如果你不小心,可能会覆盖或访问到继承来的方法(如 hasOwnProperty)。你需要使用 obj.hasOwnProperty('key') 来检查一个属性是否是自身的。

const obj = {};
console.log('toString' in obj); // true,因为从原型链继承而来

Map 是“纯净”的,它只包含你显式放入的键值对,没有任何默认的键,因此更安全。

const map = new Map();
console.log(map.has('toString')); // false

6. 序列化和解析 (Serialization and Parsing)

Object 可以无缝地与 JSON 格式相互转换。

const obj = { a: 1 };
const str = JSON.stringify(obj); // '{"a":1}'
const newObj = JSON.parse(str); // { a: 1 }

Map 默认无法被 JSON.stringify 正确处理,会序列化为一个空对象 {}。你需要自己编写转换逻辑。

const map = new Map([['a', 1]]);
const str = JSON.stringify(map); // '{}'

// 转换 Map -> JSON
const mapToJson = (map) => JSON.stringify([...map]);
// 转换 JSON -> Map
const jsonToMap = (jsonStr) => new Map(JSON.parse(jsonStr));

何时使用 Map vs Object?

使用Map的场景:

  1. 键的类型未知或多样:当你需要使用非字符串/符号作为键时(如 DOM 节点、对象等)。
  2. 需要维护插入顺序:并且需要依赖这个顺序进行迭代或其他操作。
  3. 频繁地添加和删除键值对Map 在频繁更新的场景下性能优化得更好。
  4. 需要避免与原型上的键产生冲突:需要一个纯净的键值对集合时。

使用Object的场景:

  1. 处理 JSON 数据:需要频繁地进行序列化和反序列化。
  2. 结构是固定的:你需要一个“实体”来描述某个事物,其属性和方法在开发时就是已知的(例如,user = { name: 'John', age: 30 })。
  3. 需要用到“方法”:对象可以包含函数(方法),而 Map 的值虽然也可以是函数,但语法上不如对象的方法直观(obj.method() vs map.get('method')())。
  4. 使用简单的字符串键:并且不需要 Map 提供的那些高级特性(如顺序、任意键类型等)。

总结

如果你需要…那么选择…
存储任意类型的键Map
保证键值对的插入顺序Map
频繁地添加/删除元素Map
纯净的、无原型干扰的集合Map
简单的结构,已知的字符串键Object
与 JSON 无缝交互Object
包含方法(函数)Object

在现代 JavaScript 开发中,当你的需求更偏向于一个纯粹的“键值对集合”或“哈希映射”时,Map 通常是比 Object 更优的选择。

到此这篇关于s中 Map和 Object 的区别小结的文章就介绍到这了,更多相关js Map和Object区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文