有一天,恶霸在实验室里卷代码,突然有一个学妹抱着电脑来找我,问我WeakMap
和WeakSet
与Set
和Map
的主要区别是什么,这我就提起兴致了,趁这个机会给学妹普及一下渣男的性质
如果在看这篇文章之前不了解Set
和Map
,那么请移步学习一下二者的特性,话不多说,开始我们的正题。
浅浅地了解一下垃圾回收机制(gc)
我问学妹,你知道垃圾回收是什么吗,她用无辜的眼神看着我,摇了摇头,由于要透彻地了解
WeakMap
和WeakSet
的渣男特性,于是我浅浅得给她讲了一下垃圾回收及内部机制。
垃圾回收是什么?
简单概括一下垃圾回收:当一个变量不会再被调用,就会被释放,之后垃圾回收就会周期性释放它占用的内存,它可以很好的帮助我们再代码执行阶段管理内存,减轻我们开发者的负担,当我们不再使用一个变量的时候,仅仅只需要a = null
,a之前所引用的数据就会被释放,然后垃圾回收就会自动清理。
内部的原理
我看了眼学妹,她貌似懂了,那么可以精进一下,了解一下垃圾回收是怎么进行的
垃圾回收机制内部原理之一的引用计数字,一共分为三步
- 第一步:当一个变量被声明的时候计数为1
- 第二步:当这个变量被给到另外一个变量或者数据结构中,计数加1
- 第三步:当这个变量的引用在其他地方使用
null
或者其他变量引用覆盖后,计数-1 - 第四步:垃圾回收周期性自动将计数为0的变量回收
为了更好地理解这四步,我拿代码给学妹举例子
let a = "猪痞恶霸" // 声明计数为 1 let b = a // 赋值计数 +1 = 2 b = null // 覆盖释放计数 -1 = 1 a = null // 释放计数 -1 = 0 // 周期性执行垃圾回收 复制代码
看完这个例子后,学妹清楚了垃圾回收的大概,下面我就要给她灌输WeakMap
和WeakSet
的渣男特性。
WeakMap和WeakSet是什么
WeakMap
和WeakSet
是ES6中新增的数据结构,其对应着Set
和Map
,而仅仅在头部添加Weak
一词就造就了其不同的特性,主要有如下几点
- 只能接受对象作为键值
- 无法使用
clear
方法 - 弱映射的键。
- 无
size
属性且无法被遍历
那么WeakMap
和WeakSet
渣男特性是什么呢?就是弱映射的键。 为什么说这个特性是渣男特性?观众老爷往后看!
细说渣男特性
弱映射的键其实是垃圾回收机制会忽略掉WeakMap
和WeakSet
对于其他变量的引用。通俗来讲在变量被WeakMap
和WeakSet
内引用的时候,垃圾回收内部进行的引用计数不会进行计数操作,这就会导致当其他对象不再引用WeakMap
存储的对象时,WeakMap
会自动释放,后被回收掉。
抽象地讲WeakMap
和WeakSet
在找了一个女朋友后竟然不管她的死活,当女朋友再没有引用后不保护她,直接被垃圾回收掉,你说是不是渣男。
讲到这里,学妹破口大骂:渣男!我对学妹说,等一下再骂,我给你讲完的,于是我用代码给她举了个例子
let a = "猪痞恶霸" // 声明计数为 1 let zhanan = new WeakMap() zhanan.set({ a,a }) // 垃圾回收机制忽略,计数不变为 1 a = null // 释放计数 -1 = 0 // 垃圾回收销毁 复制代码
看完这个例子就在表层理解了垃圾回收忽略弱映射的键的特性,而这个特性会导致另外一个特性,无size
属性且无法被遍历。
因为弱映射的特性,所以WeakMap
和WeakSet
会随时释放,销毁,在遍历过程中可能会发生成员消失现象,所以无法对其进行遍历也无法获取其属性size
console.log(zhanan.size) // undefined 复制代码
以抽象地形式讲完了WeakMap与WeakSet的弱映射特性,学妹也听懂了,于是我收拾书包准备和学妹吃饭去,而此刻一位学弟走来:学长你能给我讲一讲吗? 我:自己百度去。。。。