Skip to content

Map 与 WeakMap 对比

Map

Map 是JavaScript中的一种键值对集合。

特点

  • 键可以是任意类型的值,包括对象、基本类型。
  • 记录了键值对的插入顺序,可以按照插入顺序对键值对进行迭代。
  • 通过 size 属性可以获取集合的大小。
  • 键不会被自动转换为字符串,与普通对象不同。

使用场景

  • 当需要高效地查找、添加或删除键值对时。
  • 当键是非字符串类型时。
  • 当需要保持键值对的插入顺序时。

WeakMap

WeakMap 是一种特殊的 Map,接受对象作为键,并且键是弱引用的。

特点

  • 只接受对象作为键。
  • 键是弱引用的,不妨碍垃圾回收器回收键所指向的对象。
  • 没有 size 属性,也不支持清空操作,因为其大小是不固定的,随着垃圾回收的运行而自动减小。
  • 键是不可枚举的,与 Map 不同。

使用场景

  • 当需要将额外的数据与对象关联起来,又不希望这种关联阻止对象被垃圾回收时。
  • 用于缓存或存储对象实例的私有数据,而又不干扰对象的垃圾回收。

Vue3 中使用 WeakMap

在 Vue3 的响应式系统中使用 WeakMap 而不是 Map,主要是因为:

  • 内存管理WeakMap 可以确保一旦响应式对象不再被使用,就能被垃圾回收,避免内存泄漏。
  • 避免内存泄漏:使用 Map 的话,即使响应式对象不再被引用,它们也会因为在 Map 中的引用而被保留在内存中。WeakMap 通过弱引用避免了这个问题。

使用 WeakMap 优化内存使用并防止内存泄漏,是Vue3选择它作为存储副作用方式的原因。

CodeDemo

javascript
var eleImage = document.getElementById('img')
var storage = {
  arrDom: [eleImage, eleImage.outerHTML]
}
eleImage.remove()
eleImage = null

setTimeout(() => {
  document.body.append(storage.arrDom[0])
  //storage.arrDom = null;
}, 2000)
var eleImage = document.getElementById('img')
var storage = {
  arrDom: [eleImage, eleImage.outerHTML]
}
eleImage.remove()
eleImage = null

setTimeout(() => {
  document.body.append(storage.arrDom[0])
  //storage.arrDom = null;
}, 2000)

当 eleImage 被设置为 null 时,如果没有其他引用指向这个 DOM 元素,那么它就会被 JavaScript 的垃圾回收机制回收。 然而,在这个例子中,eleImage 仍然被 storage.arrDom 数组引用,所以它不会被垃圾回收。
接下来,我们可以添加一些代码来观察垃圾回收的行为。我们可以在 setTimeout 函数中,再次将 storage.arrDom 设置为 null,然后观察 eleImage 是否会被垃圾回收。storage.arrDom 被设置为 null。这时,如果没有其他引用指向 eleImage,那么它就会被 JavaScript 的垃圾回收机制回收