Skip to content
字数
1123 字
阅读时间
5 分钟

强引用和弱引用 ​

从 1 套代码结合两张图来理解

对于强引用 ​

js
const myMap = new Map()
let my = {
    name: "ljc",
    sex: "男"
}
myMap.set(my, 'info');
console.log(myMap);

image-20210725161643051

对于弱引用 ​

js
const myMap = new WeakMap()
let my = {
    name: "ljc",
    sex: "男"
}
myMap.set(my, 'info');
console.log(myMap);

image-20210725161619701

图一中的数据被 my 和 myMap 实例对象所引用,引用计数为 2,图 2 中建立了 myMap 对 my 所引用的对象的弱引用,引用计数为 1

在上面我们谈到强引用数据被删除时,需要手动解除引用,而弱引用则可以等待垃圾回收机制自动清除

weaMap ​

WeakMap 保持了对键名所引用的对象的弱引用,即垃圾回收机制不将该引用考虑在内

只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存

WeakMap 的使用场景 ​

DOM 节点元数据 ​

用红宝书的例子

因为 weakMap 不会影响垃圾回收,所以可以用来关联元数据

image-20210725171056590

当上面代码执行后,登录按钮从 DOM 树中被删除了,但由于 Map 对节点对象是强引用关系,仍然保存着对按钮的引用,所以会引起内存泄漏

image-20210725171352098

因此可以采用 WeakMap 当节点删除后,引用计数为 0,等待垃圾回收机制回收

WeakMap 部署私有属性 ​

Map 和 WeakMap 都可以部署私有属性,只是前者存在内存泄露的问题,而后者因为弱引用的特性会随着实例的消失,私有属性也会消失

javascript
// const privateData = new Map();
const privateData = new WeakMap();

class Person {
    constructor(name, age) {
        privateData.set(this, { name: name, age: age });
    }

    getName() {
        return privateData.get(this).name;
    }

    getAge() {
        return privateData.get(this).age;
    }
}

const person = new Person('x', 12)
const person2 = new Person('y', 21)

console.log(person.getName())
console.log(person2.getName())

数据缓存 ​

当我们需要在不修改原有对象的情况下储存某些属性等,而又不想管理这些数据时,可以使用 WeakMap
image-20210725173257029

针对 const 的意义 ​

主要保护引用不被修改 (如用 Map 等接口对引用的变化很敏感 (使用 WeakMap 的时候,外部用 const 定义一个对 map 中某个值的引用,可以防止这个值被 gc

查找和遍历的性能方面 ​

Map 优于 WeakMap

在查找方面,由于 WeakMap 的键是弱引用,它的查找效率要比 Map 低一些。因为在 WeakMap 中,需要通过键对象的哈希值去查找键值对,然后再判断键对象是否存在,这个过程会增加查找时间。

在遍历方面,Map 是一种可以迭代的数据结构,可以通过 for...of 等语句进行遍历。而 WeakMap 由于键对象的弱引用,无法遍历键对象。因此,WeakMap 内部只能使用迭代器模式,通过 Map 的实例进行遍历

查找的原理 ​

虽然 WeakMap 和 Map 都是基于哈希表实现的,但它们的实现方式不同。

Map 会对键值对的键进行哈希,然后将其存储在内部的存储桶中。在查找键时,首先会将键哈希为一个桶号,然后查找该桶中是否有与其匹配的键值对。如果桶中有多个键值对,则需要按照某种方式来处理哈希冲突。因此,在大部分情况下,Map 的查找速度非常快。

WeakMap 的实现方式略有不同。由于键是弱引用,WeakMap 内部存储的是键的地址的引用(即弱引用)。在查找键时,WeakMap 会将键转换成内部的地址引用,然后在内部的存储桶中查找该地址引用是否存在。因为 WeakMap 的键是弱引用,所以当键的引用被垃圾回收时,与之相关联的键值对也会被自动移除,从而避免了内存泄漏。但是由于 WeakMap 内部需要维护引用,所以在查找和遍历时,相对于 Map 会有一些性能上的损失。

参考 ​

浅析 Map 和 WeakMap 区别以及使用场景 - 掘金

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

用 ♥ 撰写