在 JavaScript 中,new Map 和普通对象 {} 都是键值对集合,但它们有重要区别:
1. 键的类型
Map - 键可以是任意类型
1 2 3 4 5 6 7 8 9 10 11 12
| const map = new Map();
map.set('string', '字符串键'); map.set(123, '数字键'); map.set(true, '布尔键'); map.set({}, '对象键'); map.set([], '数组键'); map.set(function() {}, '函数键');
console.log(map.get(123));
|
对象 - 键只能是字符串或 Symbol
1 2 3 4 5 6 7 8 9 10
| const obj = {};
obj['string'] = '字符串键'; obj[123] = '数字键'; obj[{}] = '对象键'; obj[[1,2]] = '数组键';
console.log(obj);
|
2. 顺序保证
Map - 保持插入顺序
1 2 3 4 5 6 7 8 9 10
| const map = new Map(); map.set('z', 1); map.set('a', 2); map.set('m', 3);
for (let [key, value] of map) { console.log(key); }
|
对象 - 不保证顺序(现代JS有改进但仍有差异)
1 2 3 4 5 6 7 8 9 10 11
| const obj = { z: 1, a: 2, m: 3 };
for (let key in obj) { console.log(key); }
|
3. 大小获取
Map - 有 size 属性
1 2 3 4 5 6
| const map = new Map(); map.set('a', 1); map.set('b', 2);
console.log(map.size);
|
对象 - 需要手动计算
1 2 3
| const obj = { a: 1, b: 2 }; console.log(Object.keys(obj).length);
|
4. 性能差异
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const map = new Map(); const obj = {};
console.time('Map添加'); for (let i = 0; i < 100000; i++) { map.set(i, i); } console.timeEnd('Map添加');
console.time('对象添加'); for (let i = 0; i < 100000; i++) { obj[i] = i; } console.timeEnd('对象添加');
|
5. 方法和特性对比
Map 方法
1 2 3 4 5 6 7 8 9
| const map = new Map();
map.set('key', 'value'); map.get('key'); map.has('key'); map.delete('key'); map.clear(); map.forEach((value, key) => {});
|
对象方法
1 2 3 4 5 6 7 8
| const obj = {};
obj.key = 'value'; obj.key; 'key' in obj; delete obj.key; Object.keys(obj).forEach(key => {});
|
6. 原型链问题
Map - 没有原型链干扰
1 2 3
| const map = new Map(); console.log(map.get('toString'));
|
对象 - 有原型链
1 2 3 4 5 6 7
| const obj = {}; console.log(obj.toString);
const safeObj = Object.create(null); console.log(safeObj.toString);
|
7. 序列化
对象 - 可 JSON 序列化
1 2 3
| const obj = { a: 1, b: 2 }; console.log(JSON.stringify(obj));
|
Map - 不能直接序列化
1 2 3 4 5 6
| const map = new Map([['a', 1], ['b', 2]]); console.log(JSON.stringify(map));
console.log(JSON.stringify([...map]));
|
8. 使用场景总结
使用 Map 的情况:
- 键类型多样(对象、函数等作为键)
- 需要频繁增删键值对
- 需要保持插入顺序
- 大数据量操作
使用对象的情况:
- 键都是字符串或 Symbol
- 需要 JSON 序列化
- 简单的配置、数据存储
- 方法和属性的集合
1 2 3 4 5 6 7 8 9 10
| const userSessions = new Map();
const config = { apiUrl: 'https://api.example.com', timeout: 5000, retryCount: 3 };
|
选择依据:如果需要复杂键或高性能操作,用 Map;如果是简单数据结构,用对象。