Map/Set 和 WeakMap/WeakSet 的区别?使用场景是什么?

对比表

特性 Map WeakMap Set WeakSet
键类型 任意 仅对象 — —
值类型 任意 任意 — 仅对象
可遍历 ✅ ❌ ✅ ❌
强引用 ✅ ❌(弱引用) ✅ ❌(弱引用)
size 属性 ✅ ❌ ✅ ❌
GC 回收 不会 会 不会 会

Map

const map = new Map()
map.set('name', 'Tom')
map.set(1, 'number key')     // 任意类型键
map.set({ id: 1 }, 'object key')

map.get('name')   // 'Tom'
map.has('name')   // true
map.size          // 3
map.forEach((v, k) => console.log(k, v))

Set

const set = new Set([1, 2, 2, 3, 3])
set.size          // 3(自动去重)
set.add(4)
set.has(2)        // true
set.delete(1)

// 数组去重
const unique = [...new Set([1, 1, 2, 3, 3])]

WeakMap — 弱引用映射

const wm = new WeakMap()
let obj = { name: 'Tom' }
wm.set(obj, 'metadata')

// 当 obj 被回收,wm 中的条目也会被自动清除
obj = null  // 触发 GC 后,wm 中对应条目消失

使用场景

WeakMap:

  1. DOM 节点关联数据(节点被移除时数据自动清理)
const elementData = new WeakMap()
elementData.set(domElement, { listeners: [], state: {} })
  1. 私有属性存储
const privateFields = new WeakMap()
class Person {
  constructor(name) {
    privateFields.set(this, { _name: name })
  }
  getName() { return privateFields.get(this)._name }
}
  1. 缓存(对象被回收时缓存自动失效)

WeakSet:

  1. 对象标记(标记某对象是否被处理过)
const processed = new WeakSet()
function handle(obj) {
  if (processed.has(obj)) return
  // 处理 obj...
  processed.add(obj)
}

同分类其他题目