好的!Map
是 ES6 引入的一种键值对数据结构,与传统的 Object
不同,它的键可以是任意类型(对象、函数、原始类型),且保留元素插入顺序。以下是核心用法和场景解析:
一、基本特性对比(Map vs Object)
特性 | Map | Object |
---|---|---|
键的类型 | 任意类型(包括对象) | 仅字符串或 Symbol |
遍历顺序 | 插入顺序 | 无序(ES6后对象也有序但复杂) |
性能 | 频繁增删时更优 | 静态键值对时略快 |
序列化 | 无法直接 JSON.stringify | 支持 |
默认键 | 无 | 有原型链可能带来冲突键 |
二、Map 核心用法
1. 初始化与增删改查
// 初始化
const map = new Map();
// 添加键值对(键可以是对象、函数等)
const keyObj = { id: 1 };
map.set('name', 'Alice'); // 字符串键
map.set(keyObj, 'Value1'); // 对象键
map.set(100, 'Century'); // 数字键
// 获取值
console.log(map.get('name')); // 'Alice'
console.log(map.get(keyObj)); // 'Value1'
// 判断键存在性
console.log(map.has(100)); // true
// 删除键
map.delete('name');
// 清空
// map.clear();
// 大小
console.log(map.size); // 2
2. 遍历方法
const map = new Map([
['a', 1],
['b', 2]
]);
// for...of 遍历
for (const [key, value] of map) {
console.log(key, value); // 'a' 1, 'b' 2
}
// forEach 遍历
map.forEach((value, key) => {
console.log(key, value);
});
// 获取键、值、条目集合
console.log([...map.keys()]); // ['a', 'b']
console.log([...map.values()]); // [1, 2]
console.log([...map.entries()]); // [['a', 1], ['b', 2]]
三、高级用法场景
1. 用对象作为键(避免引用泄漏)
const user1 = { id: 1 }, user2 = { id: 2 };
const permissions = new Map();
permissions.set(user1, ['read', 'write']);
permissions.set(user2, ['read']);
console.log(permissions.get(user1)); // ['read', 'write']
2. 存储函数元数据
const funcRegistry = new Map();
const func = () => console.log('Hello');
funcRegistry.set(func, {
author: 'Alice',
version: '1.0'
});
console.log(funcRegistry.get(func).author); // 'Alice'
3. 缓存计算结果(Memoization)
const cache = new Map();
function computeExpensiveValue(key) {
if (cache.has(key)) {
return cache.get(key);
}
const result = /* 复杂计算 */ key.toUpperCase();
cache.set(key, result);
return result;
}
四、与 Object/Array 转换
1. Map ↔ 二维数组
// Map → 数组
const map = new Map([['a', 1], ['b', 2]]);
const arr = Array.from(map); // [['a', 1], ['b', 2]]
// 数组 → Map
const newMap = new Map(arr);
2. Map → Object(键需为字符串)
const map = new Map([['name', 'Bob'], [Symbol(), 'secret']]);
const obj = Object.fromEntries(map);
console.log(obj); // { name: 'Bob' } (Symbol键被忽略)
五、性能优化场景
1. 高频增删键值对
// 使用 Map 更高效
const dynamicKeys = new Map();
for (let i = 0; i < 1000; i++) {
dynamicKeys.set(i, Math.random());
}
dynamicKeys.delete(500); // 比 delete object[key] 更快
2. 避免键冲突
// 使用 Map 避免原型链污染
const safeMap = new Map();
safeMap.set('toString', 'customValue'); // 安全
const obj = {};
obj['toString'] = 'customValue'; // 覆盖原型方法,引发意外行为
六、注意事项
- 内存管理:如果键是对象,Map 会强引用该对象,可能导致内存泄漏(需手动删除或使用 WeakMap)。
- 类型严格:
map.get(1)
和map.get('1')
视为不同键。 - 迭代消耗:频繁遍历时优先用
for...of
而非forEach
。
如果需要更专业的应用场景(如与 WeakMap 对比)或具体编程问题,可以继续提问! 🚀