Map 和 WeakMap 是 JavaScript 中用于存储键值对的数据结构,它们在用法上有一些相似之处,但也有关键的区别,主要在于键的类型、垃圾回收行为以及可迭代性等方面。以下是它们的核心区别:
✅ 1. 键(Key)的类型
| Map |
WeakMap |
| 键可以是任意类型(对象或基本类型) |
键必须是对象(不能是基本类型) |
let map = new Map();
map.set('a', 1); // 字符串作为键
map.set({}, 2); // 对象作为键
let weakMap = new WeakMap();
weakMap.set({}, 2); // 只能用对象作为键
// weakMap.set('a', 1); // ❌ 报错:无效键(TypeError: Iterator value a is not an entry object)
✅ 2. 垃圾回收机制(GC)
| Map |
WeakMap |
| 对象作为键时,不会被自动垃圾回收 |
如果没有其他引用,键对象会被自动回收 |
🔍 解释 :WeakMap 中的键是"弱引用",不会阻止垃圾回收机制回收该对象。
let obj = {};
let map = new Map();
let weakMap = new WeakMap();
map.set(obj, 'value');
weakMap.set(obj, 'value');
obj = null;
// Map 中的键值对仍然存在(引用保留)
console.log(map); // 仍包含原对象作为键
// WeakMap 的键值对可能会被回收(无法检测)
✅ 3. 可迭代性
| Map |
WeakMap |
是可迭代的(可使用 forEach、for...of、entries() 等) |
不是可迭代的,无法遍历键值对 |
let map = new Map();
map.set('a', 1);
for (let [key, val] of map) {
console.log(key, val);
}
// WeakMap 不支持迭代:
let weakMap = new WeakMap();
// weakMap.forEach(...) ❌ 错误
✅ 4. 用途场景
| Map 用途 |
WeakMap 用途 |
| 需要任意类型的键,且需要可遍历和操作全部键值对 |
适用于给对象绑定私有数据或缓存信息,且不影响对象回收 |
✅ 5. API 对比
| 功能 |
Map |
WeakMap |
set(key, val) |
✅ 支持 |
✅ 支持 |
get(key) |
✅ 支持 |
✅ 支持 |
has(key) |
✅ 支持 |
✅ 支持 |
delete(key) |
✅ 支持 |
✅ 支持 |
| 遍历 |
✅ forEach, for...of |
❌ 不支持 |
size 属性 |
✅ 支持 |
❌ 不支持 |
✅ 总结对比表
| 特性 |
Map |
WeakMap |
| 键的类型 |
任意类型 |
只能是对象 |
| 是否可迭代 |
是 |
否 |
| 垃圾回收关联 |
否 |
是(键可被自动回收) |
| 用途 |
通用键值存储 |
私有数据关联 / 缓存 |
如果你需要缓存绑定在对象上的一些信息,又不想影响垃圾回收,用 WeakMap。如果你需要完整地追踪、遍历或使用任何类型的键,用 Map。