Map和WeakMap
# JavaScript 中 Map
与 WeakMap
的区别、联系及示例
# 核心区别
特性 | Map | WeakMap |
---|---|---|
键的类型 | 允许任意类型的键(对象、原始值) | 键必须是对象(非原始值) |
垃圾回收 | 强引用键 → 阻止垃圾回收 | 弱引用键 → 不影响垃圾回收 |
可遍历性 | 支持遍历(keys() , values() , entries() ) | 不可遍历(无遍历方法) |
Size 属性 | 有 size 属性获取键值对数量 | 无 size 属性 |
清除方法 | 有 clear() 方法 | 无 clear() 方法 |
性能 | 频繁增删时内存占用较高 | 内存优化(自动清理无引用键值对) |
# 核心联系
- 键值对存储
二者均为键值对集合:set(key, value)
/get(key)
/has(key)
/delete(key)
- 键的唯一性
键具有唯一性(引用不同的对象视为不同键)
# 代码示例
# 1. Map 基本用法
const user = { id: 1 };
const settingsMap = new Map();
// 添加任意类型键
settingsMap.set(user, { theme: "dark" }); // ✅ 对象键
settingsMap.set("language", "en"); // ✅ 字符串键
console.log(settingsMap.size); // 2
console.log(settingsMap.get(user)); // { theme: "dark" }
// 遍历Map
for (const [key, val] of settingsMap) {
console.log(`${key}: ${JSON.stringify(val)}`);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2. WeakMap 基本用法
const user = { id: 1 };
const metadata = new WeakMap();
metadata.set(user, { lastLogin: "2023-10-05" }); // ✅ 只允许对象键
// metadata.set("role", "admin"); // ❌ TypeError
console.log(metadata.has(user)); // true
console.log(metadata.get(user)); // { lastLogin: "2023-10-05" }
// 当对象被销毁时
user = null; // 移除对user对象的引用
// 垃圾回收后,WeakMap自动删除对应键值对
// metadata.get(user) → undefined (无法直接验证)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 高级场景示例
# 场景 1:Map 的强引用问题
let data = { key: "value" };
const map = new Map();
map.set(data, 1);
data = null; // 移除引用
// Map仍保留键值对 → 内存泄漏
console.log([...map.keys()]); // [{ key: "value" }]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 场景 2:WeakMap 解决内存泄漏
let data = { key: "value" };
const weakMap = new WeakMap();
weakMap.set(data, 1);
data = null; // 移除唯一引用
// 垃圾回收后,weakMap自动清除键值对
// 无法直接检查,但内存被释放
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 场景 3:私有属性模拟(WeakMap)
const privateStore = new WeakMap();
class User {
constructor(name) {
// 每个实例关联私有数据
privateStore.set(this, { name });
}
getName() {
return privateStore.get(this).name;
}
}
const alice = new User("Alice");
console.log(alice.getName()); // "Alice"
// 外部无法访问私有数据
console.log(alice.name); // undefined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 使用建议
场景 | 推荐 | 原因 |
---|---|---|
需要遍历键/值 | Map | 支持遍历操作 |
存储原始值作为键 | Map | WeakMap 不支持原始值键 |
管理对象私有数据 | WeakMap | 避免内存泄漏,自动清理 |
临时关联对象与元数据 | WeakMap | 对象销毁时自动解除关联 |
缓存大量长期数据 | Map | WeakMap 无大小控制和遍历能力 |
核心总结:优先使用
Map
通用场景;选择WeakMap
需满足 键是对象 + 需自动内存管理 两大条件。
编辑 (opens new window)
上次更新: 2025/08/04, 08:16:58