WeakMap 和 WeakSet

1. 什么是 WeakSet WeakSet 结构与 Set 类似,也是不重复的值的集合,具备 WeakSet.prototype.add(value) :向 WeakSet 实例添加一个新成员。 WeakSet.prototype.delete(value) :清除 WeakSet 实例的指定成员。 WeakSet.prototype.has(value) :返回一个布尔值,表示某个值是否在 WeakSet 实例之中。 这三个方法。但是,它与 Set 有两个区别。 区别一:WeakSet 的成员只能是对象和Symbol类型,而不能是其他类型的值,我们用代码演示一下 从代码中可以看到,想像Set一样直接往 WeakSet 中添加原始类型化会报错,只能添加对象和Symbol 区别二(这是核心): WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。 (这句解释来自ECMAScript 6 入门,第一眼看到这句话这话会觉得有点晦涩,我们来解释一下) 弱引用:垃圾回收机制有一套自己的回收算法,我们都知道一个函数执行完成后该函数在调用栈中创建的执行上下文会被销毁,这里说的销毁,其实指的就是执行上下文中环境变量、词法变量中的数据存储所占据的内存空间被垃圾回收机制所回收,那么垃圾回收机制不考虑 WeakSet 对该对象的引用是不是就意味着垃圾回收机制不会回收 WeakSet 对象里面的数据所占据的内存呢?不!不是的!代码是最好的解释 我们用 ws 中存放一个对象,然后再将该对象置为null,(这里要说明一下,一个变量被置为null,就意味着这个变量的内存可以被回收了)看着这个打印结果有没有突然明白了点什么,对!没错!只要 WeakSet 结构中的对象不再需要被引用,那么 WeakSet 就直接为空了,这不就意味着WeakSet中的数据所占据的内存被释放了吗。好的,你或许还会有疑问,难道不用 WeakSet 存储数据,结果就不是这样的吗,来打消你的疑虑 不使用 WeakSet 存放数据,当变量obj为null时,fistName依旧是有值的,对比这段代码,我们可以清晰的看出, WeakSet中 - 垃圾回收机制会自动回收该对象所占用的内存 2. 这里有’BUG' 可能已经有小伙伴拔出了他40米长的大剑了,上图二中的代码其实有问题,真实的打印应该是 各位手中的长剑收一收,先别急,其实我们前面聊的没有问题,为什么这里真是打印能出来结果呢?这个问题在国外某技术论坛上也是一度出现在 WeakSet 话题榜首位,解释为:因为浏览器的垃圾回收机制是不受我们控制的,我们无法知道垃圾回收机制什么时候执行,之所以打印能出现内容,其实是因为打印的时候垃圾回收机制没有启动。所以我们可以认为,上图二中的打印在垃圾回收启动之后,它就是空的 我们可以这样来证明它: 如果这样你觉得依旧不够睡服你自己的话,我们把这段代码搬到node中: ...

October 2, 2024