「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
Hope is a good thing, maybe the best of things. And no good thing ever dies.
前戏-Map
ES6 提出了新的数据结构- Map,它类似对象, 但是比对象更加的灵活。它的键(key)可以是任意的数据类型,不在拘泥于字符串和Symbol。
关于 Map ,可以参考我之前总结过的一篇文章:「我竟然有点忘记了 ES6 的Map😅😅」,这里就不再啰嗦了。
附上文章链接:
为什么有了 WeakMap
上面我们可以知道 Map 的使用场景和用法,既然有了 Map ,为什么还有一个 WeakMap 呢?
首先我就要知道 WeakMap 和 Map 的主要区别是什么。
WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。
区别1
WeakMap 只接受对象作为键名(null除外),不接受其他类型的值作为键名
const map = new WeakMap();
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key
区别2
WeakMap 的键名所指向的对象,不计入垃圾回收机制
WeakMap 的设计目的在于,有时我们想在某个对象上面存放一些数据,但是这会形成对于这个对象的引用
const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
[e1, 'foo 元素'],
[e2, 'bar 元素'],
];
上面的代码中,e1和e2是两个对象,我们通过arr数组对这两个对象添加一些文字说明。这就形成了arr对e1和e2的引用
一旦不再需要这两个对象,我们就必须手动删除这个引用,否则垃圾回收机制就不会释放e1和e2占用的内存。
// 不需要 e1 和 e2 的时候
// 必须手动删除引用
arr [0] = null;
arr [1] = null;
上面的写法,一旦忘了写,就会造成内存泄露
WeakMap 就是为了解决这个问题,它的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用
如果要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用
WeakMap
WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏
WeakMap弱引用的只是键名,而不是键值。键值依然是正常引用
WeakMap 语法
由于没有办法列出所有键名,某个键名是否存在完全不可预测,跟垃圾回收机制是否运行相关。这一刻可以取到键名,下一刻垃圾回收机制突然运行了,这个键名就没了,为了防止出现不确定性,就统一规定不能取到键名。二是无法清空,即不支持clear方法。
与 Map 相比,它是没有遍历操作(即没有keys()、values()和entries()方法),也没有size属性。
WeakMap只有四个方法可用:get()、set()、has()、delete()
WeakMap 经典用法
WeakMap应用的典型场合就是DOM节点作为键名。
let myWeakmap = new WeakMap();
myWeakmap.set(
document.getElementById('logo'),
{timesClicked: 0})
;
document.getElementById('logo').addEventListener('click', function() {
let logoData = myWeakmap.get(document.getElementById('logo'));
logoData.timesClicked++;
}, false);
document.getElementById('logo')是一个 DOM 节点,每当发生click事件,就更新一下状态。我们将这个状态作为键值放在 WeakMap 里,对应的键名就是这个节点对象。一旦这个 DOM 节点删除,该状态就会自动消失,不存在内存泄漏风险。
WeakMap的另一个用处是部署私有属性
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」