「这是我参与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
的另一个用处是部署私有属性
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」