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 的垃圾回收机制回收