【js篇】Map 和 WeakMap 的区别详解

286 阅读3分钟

在 JavaScript 中,MapWeakMap 都是用于存储键值对的数据结构,它们都允许使用对象作为键,这是与普通 Object 不同的地方。但两者在键的类型、垃圾回收机制、可操作性等方面存在显著差异。


✅ 一句话总结

Map 是一个通用的键值对集合,键可以是任意类型;WeakMap 则只能使用对象作为键,并且键是弱引用的,不会阻止垃圾回收,适用于临时存储对象元数据。


✅ 一、基础对比表格

特性MapWeakMap
键的类型任意类型(对象、基本类型、函数)只能是对象(不能是 null 以外的基本类型)
弱引用机制不具备弱引用键是弱引用,不影响垃圾回收
是否可迭代可迭代(支持 forEachentries() 等)不可迭代
clear() 方法无(已弃用)
size 属性
用途存储任意键值对,适合长期存储存储对象的临时数据,防止内存泄漏

✅ 二、详细对比说明

🔹 1. 键的类型

Map

  • 键可以是任意类型,包括:
    • 基本类型(字符串、数字、布尔值)
    • 对象
    • 函数
    • Symbol
const map = new Map();

map.set('string', 'value');
map.set(123, 'number');
map.set(true, 'boolean');
map.set({ key: 'obj' }, 'object');
map.set(() => {}, 'function');

WeakMap

  • 只能使用对象作为键(包括 null),不能使用原始类型(如数字、字符串)。
const weakMap = new WeakMap();

const obj = {};
weakMap.set(obj, 'value'); // ✅ 正确

weakMap.set('string', 'value'); // ❌ 报错:Invalid value used as weak map key

🔹 2. 弱引用机制(核心区别)

Map

  • 如果你把一个对象作为键存入 Map,那么这个对象将不会被垃圾回收机制回收,即使你不再使用它。
let obj = {};
const map = new Map();
map.set(obj, 'value');

obj = null; // 试图释放内存

console.log(map.get(obj)); // undefined,但 obj 仍被 map 引用,无法回收

WeakMap

  • 如果键对象没有其他引用,它将被垃圾回收机制回收,WeakMap 中对应的键值对也会被自动清除。
let obj = {};
const weakMap = new WeakMap();
weakMap.set(obj, 'value');

obj = null; // obj 没有其他引用,会被回收

console.log(weakMap.get(obj)); // undefined

📌 说明:

  • WeakMap 的键是“弱引用”,不会阻止垃圾回收;
  • 适用于临时存储对象元数据,如缓存、私有属性等,防止内存泄漏。

🔹 3. 是否可迭代

Map

  • 是可迭代对象,支持:
    • map.forEach()
    • map.keys()
    • map.values()
    • map.entries()
map.forEach((value, key) => {
  console.log(key, value);
});

WeakMap

  • 不可迭代,不支持上述方法;
  • 也不能获取键或值的集合;
  • 不支持 size 属性;
  • 不支持 clear()(有些环境已弃用);
for (let key of weakMap.keys()) { // ❌ 报错:weakMap.keys is not a function
}

🔹 4. 用途与适用场景

场景推荐使用
需要存储任意类型的键Map
需要遍历、统计键值对数量Map
需要清除所有键值对Map
为对象存储元数据、缓存WeakMap
防止内存泄漏WeakMap
键对象可能被垃圾回收WeakMap

✅ 三、代码示例对比

示例 1️⃣:Map 的使用

const map = new Map();

const obj = {};
map.set(obj, 'value');

console.log(map.get(obj)); // 'value'
console.log(map.size);     // 1

map.forEach((value, key) => {
  console.log(key, value); // 输出对象和值
});

示例 2️⃣:WeakMap 的使用

const weakMap = new WeakMap();

const obj = {};
weakMap.set(obj, 'value');

console.log(weakMap.get(obj)); // 'value'

// 删除引用后,键值对会自动被回收
obj = null;

console.log(weakMap.get(obj)); // undefined

✅ 四、一句话总结

Map 是功能完整、通用性强的键值对结构,适合长期存储和遍历;WeakMap 是轻量级的、键为弱引用的结构,适合临时存储对象元数据,避免内存泄漏。根据使用场景选择合适的数据结构,是写出高效、安全代码的关键。


💡 进阶建议

  • 在 React/Vue 中,WeakMap 常用于组件实例的私有状态管理;
  • 使用 WeakMap 可以实现“私有属性”或“元数据绑定”;
  • Map 可用于缓存、计数器、字典等场景;
  • 使用 TypeScript 时,MapWeakMap 都支持类型标注;