在 JavaScript 中,Object 和 Map 都可以用来存储键值对,但它们在键的类型、键的顺序、迭代方式、性能表现等方面存在显著差异。理解这些差异有助于我们在不同场景中选择合适的数据结构。
✅ 一句话总结
Map是一种更现代、更灵活的键值对结构,支持任意类型的键、保持插入顺序、易于迭代和获取大小;而Object虽然更基础,但在处理复杂键和频繁操作时存在局限性。
✅ 一、基础对比表格
| 特性 | Map | Object |
|---|---|---|
| 默认键 | 默认无键,只有显式添加的键值对 | 有原型链,可能包含继承的键 |
| 键的类型 | 可以是任意类型(函数、对象、基本类型) | 只能是 string 或 symbol |
| 键的顺序 | 保持插入顺序 | 顺序不保证(ES6 以前) |
| 键值对数量 | 可通过 .size 属性直接获取 | 需要手动计算(如 Object.keys(obj).length) |
| 是否可迭代 | 原生可迭代(支持 for...of) | 不可直接迭代,需先获取键列表 |
| 性能 | 更适合频繁增删键值对的场景 | 在频繁操作下性能较差 |
✅ 二、详细对比说明
🔹 1. 键的类型
Map:
- 支持任意类型的键,包括对象、函数、数字、布尔值等。
const map = new Map();
const key1 = {};
map.set(key1, 'value for object key');
const key2 = function () {};
map.set(key2, 'value for function key');
console.log(map.get(key1)); // 'value for object key'
console.log(map.get(key2)); // 'value for function key'
Object:
- 键只能是字符串或 Symbol,其他类型会自动转换为字符串。
const obj = {};
const key = {};
obj[key] = 'value';
console.log(obj[key]); // 'value'
console.log(obj[{}] === obj['[object Object]']); // true
🔹 2. 插入顺序是否保留
Map:
- 保持插入顺序,迭代时按插入顺序返回键值对。
const map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);
for (const [key, value] of map) {
console.log(key, value); // a 1 → b 2 → c 3
}
Object:
- ES6 之前键是无序的,ES6 规范后虽然大部分实现保持插入顺序,但不保证。
const obj = {
b: 2,
a: 1,
c: 3
};
console.log(Object.keys(obj)); // ['b', 'a', 'c'](可能因环境而异)
🔹 3. 是否包含原型链上的键
Map:
- 只包含显式插入的键值对,不会包含原型链上的键。
Object:
- 如果对象的原型链上有属性,可能会与自身属性冲突。
const obj = {};
obj.hasOwnProperty('toString'); // false
console.log('toString' in obj); // true(来自原型链)
🔹 4. 获取键值对个数
Map:
- 可以通过
.size属性直接获取键值对数量。
const map = new Map();
map.set('a', 1);
map.set('b', 2);
console.log(map.size); // 2
Object:
- 需要手动计算,比如使用
Object.keys(obj).length。
const obj = { a: 1, b: 2 };
console.log(Object.keys(obj).length); // 2
🔹 5. 可迭代性
Map:
- 原生可迭代,支持
for...of、展开运算符等。
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
console.log([...map]); // [ ['a', 1], ['b', 2], ['c', 3] ]
Object:
- 不可直接迭代,需要先获取键或值数组。
const obj = { a: 1, b: 2 };
console.log([...Object.keys(obj)]); // ['a', 'b']
🔹 6. 性能表现
Map:
- 更适合频繁增删键值对的场景;
- 插入、删除、查找性能更优(尤其是大数据量下);
Object:
- 适合静态数据或简单键值对存储;
- 在频繁操作下性能略差;
✅ 三、适用场景对比
| 场景 | 推荐使用 |
|---|---|
| 存储任意类型的键(如函数、对象) | Map |
| 需要保持键的插入顺序 | Map |
| 需要频繁增删键值对 | Map |
| 与 JSON 交互、属性访问语法简洁 | Object |
| 使用字符串或 Symbol 作为键 | Object 或 Map |
| 需要兼容旧浏览器或库 | Object |
✅ 四、一句话总结
Map是 JavaScript 中更现代、更灵活的键值对结构,适用于键类型复杂、需保持顺序、频繁操作等场景;而Object更适合简单的键值对存储,尤其在与 JSON 交互或需要兼容旧环境时更常用。