强引用
在JS中,如果我们将一个引用通过变量或常量保存时,那么这个变量或常量就是强引用。在内部,有一条线将这个变量和引用地址连接在一起了,那么这个引用就不会被当作“垃圾”回收掉。而如果我们为该引用又分配给了一个新的变量,那么在内存当中,又会为这个新变量和该引用创建一根新的“线”将他们连接在一起。
const user = {name:"alex"}
const user2 = user
在上面的代码中,我们将一个引用:{name:"alex"}
赋值给了user。那么在实际的内存当中,就会有一根线连接user和该引用:
然后我们又创建了一个变量user2
,并将user赋值给该变量,这里赋值的值其实就是这个引用,所以相当于是这样的关系:
接下来我们再来看当我们使用ES6新引入的类型WeakSet
和WeakMap
在存储引用值时,是一种什么样的情况。
弱引用
ES6新引入有多种类型,其中就有包括WeakSet和WeakMap两种类型,这两种类型均只能接收引用值存储,并且这些引用值都是弱引用。接下来我们着重从WeakSet中介绍这种弱引用特性,那么我们来看以下代码情况:
// 还是刚才那种定义
const user = {name:"alex"}
const user2 = user
// 我们使用WeakSet来创建一个WeakSet实例
const ws = new WeakSet()
// 我们为由WeakSet构造出的实例ws添加一个数据:user2
ws.add(user2)
到目前为止,我们多做了两件事情,第一是我们创建了一个WeakSet
实例,第二是我们在该实例中添加了一个user2,user2对应的引用值是{name:"alex"}
。那么我们用画图来表示则是以下这种情况:
你会看到,ws实例中的值{name:"alex"}
引用指向于{name:"alex"}
(在实际内存中他指向的是该数据的栈的指针引用,该栈指向对应堆中的对应的那个地址的值)。并且需要特别注意的是,这条弱引用的“线”是透明的,这是什么意思?他和强引用的区别在哪里?一句话概述:强引用被{name:"alex"}
这个引用认可为一个“连接”,而弱引用不被认可。即该引用并不知道它被ws实例所引用。造成的后果就是该引用并不知道自己被ws实例所引用,这说明垃圾回收也不知道该引用被ws实例所引用。那么如果该引用的所有强引用连接都被断开了(变量被赋值为null或其他情况),那么该引用会被当作垃圾销毁,即使ws实例还在引用着该引用。
// 还是刚才那种定义
const user = {name:"alex"}
const user2 = user
// 我们使用WeakSet来创建一个WeakSet实例
const ws = new WeakSet()
// 我们为由WeakSet构造出的实例ws添加一个数据:user2
ws.add(user2)
user = null
user2 = null
console.log(ws) // {}
继续解析我们上述代码,我们在为ws实例添加了一个新的值,它指向引用{name:"alex"}
,这时我们将user和user2都赋值为null,相当于把他们的强引用连接断开。这时会发生什么?
这时,因为所有的强引用都断开了,那么垃圾回收认为该引用{name:"alex"}
不需要了,就会将他销毁。那么对应的ws实例所用到的该引用也都不复存在了,即使ws实例还在使用着该引用。这就是弱引用的特性。
萌新刚学,表达这块可能不太清楚,见谅。