ES6 的 WeakMap,你还记得吗?😬😬

313 阅读3分钟

「这是我参与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 呢?

首先我就要知道 WeakMapMap 的主要区别是什么。

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 元素'],
];

上面的代码中,e1e2是两个对象,我们通过arr数组对这两个对象添加一些文字说明。这就形成了arre1e2的引用

一旦不再需要这两个对象,我们就必须手动删除这个引用,否则垃圾回收机制就不会释放e1e2占用的内存。

// 不需要 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 经典用法

  1. 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 节点删除,该状态就会自动消失,不存在内存泄漏风险。

  1. WeakMap 的另一个用处是部署私有属性

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏

欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后