JavaScript 中 Map 和 WeakMap 的比较

42 阅读2分钟

JavaScript 中 Map 和 WeakMap 的比较

Map 和 WeakMap 都是 JavaScript 中的键值对集合,但它们有一些重要的区别:

Map (映射)

特点:

  1. 键可以是任意类型(对象、原始值等)
  2. 保持对键的强引用,防止键被垃圾回收
  3. 可遍历(可以使用 keys()values()entries() 等方法)
  4. 可以获取大小(通过 size 属性)
  5. 键是唯一的(使用 SameValueZero 算法比较)

使用场景:

  • 需要存储任意类型键值对
  • 需要遍历或获取集合大小
  • 键需要长期存在不被回收

示例:

const map = new Map();
const key = { id: 1 };

map.set(key, 'value');
console.log(map.get(key)); // 'value'
console.log(map.size); // 1

// 遍历
for (const [k, v] of map) {
  console.log(k, v);
}

WeakMap (弱映射)

特点:

  1. 键必须是对象或非全局注册的符号(Symbol)(不能是原始值)
  2. 对键保持弱引用,不影响垃圾回收
  3. 不可遍历(没有迭代方法)
  4. 无法获取大小(没有 size 属性)
  5. 键是唯一的(使用对象引用比较)

使用场景:

  • 需要以对象为键且不希望影响垃圾回收
  • 存储对象的私有或元数据
  • 不需要遍历或知道集合大小

示例:

const weakMap = new WeakMap();
const key = { id: 1 };

weakMap.set(key, 'private data');
console.log(weakMap.get(key)); // 'private data'

// 当 key 被垃圾回收后,weakMap 中的条目会自动移除

主要区别总结

特性MapWeakMap
键类型任意类型必须是对象
键引用强引用弱引用
可遍历
可获取大小是 (size 属性)
垃圾回收影响防止键被回收不阻止键被回收
性能相对较低相对较高
使用场景通用键值存储对象关联元数据

何时使用

  • 使用 Map 当:

    • 需要遍历键值对
    • 需要知道集合大小
    • 键可以是原始值
    • 需要长期保持键值对
  • 使用 WeakMap 当:

    • 只需要用对象作为键
    • 不希望影响垃圾回收
    • 不需要遍历或知道大小
    • 存储与对象关联的临时数据

WeakMap 特别适合用于实现私有属性、缓存系统或任何与对象生命周期绑定的数据存储场景。