Map
和 WeakMap
是 JavaScript 中用于存储键值对的数据结构,它们在用法上有一些相似之处,但也有关键的区别,主要在于键的类型、垃圾回收行为以及可迭代性等方面。以下是它们的核心区别:
✅ 1. 键(Key)的类型
Map | WeakMap |
---|---|
键可以是任意类型(对象或基本类型) | 键必须是对象(不能是基本类型) |
js
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
中的键是"弱引用",不会阻止垃圾回收机制回收该对象。
js
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() 等) |
不是可迭代的,无法遍历键值对 |
js
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
。