Maps与WeakMaps在DOM节点管理中的妙用( 二 )

接下来,我设置了一个模板来测量循环遍历所有这些行并将一些相关状态存储在对象或Map中需要多长时间 。我还在 for 循环中运行了同样的过程多次,然后确定编写和读取所需的平均时间 。
const rows = document.querySelectorAll('tr');const times = [];const testMap = new Map();const testObj = {};for (let i = 0; i < 1000; i++) {const start = performance.now();rows.forEach((row, index) => {// Test Case #1// testObj[row.id] = index; // const result = testObj[row.id]; // Test Case #2 // testMap.set(row, index); // const result = testMap.get(row);});times.push(performance.now() - start);}const average = times.reduce((acc, i) => acc + i, 0) / times.length;console.log(average);我用不同的行大小运行了这个测试:
【Maps与WeakMaps在DOM节点管理中的妙用】 

Maps与WeakMaps在DOM节点管理中的妙用

文章插图
 
请记住,即使是稍微不同的情况,这些结果也可能会有很大的差异,但总体而言,它们通常符合我的预期 。在处理相对较少的项目时,Map 和对象之间的性能是可比的 。但随着项目数量的增加,Map 开始拉开差距 。性能的次线性变化开始显现 。
WeakMaps更有效地管理内存有一个特殊版本的 Map 接口,旨在更好地管理内存 - WeakMap。它通过保持对其键的“弱”引用来实现这一点,因此,如果这些对象键中的任何一个不再具有其他地方绑定的引用,则它有资格进行垃圾回收 。因此,当不再需要该键时,整个条目将自动从 WeakMap 中删除,从而清除更多内存 。它也适用于DOM节点 。
为了调整这个,我们将使用 FinalizationRegistry ,它会在你正在观察的引用被垃圾回收时触发回调 。我们将从几个列表项开始:
<ul><li id="item1">first</li><li id="item2">second</li><li id="item3">third</li></ul>接下来,我们将把这些项目放入 WeakMap 中,并将 item2 注册为注册表监视的对象 。我们将其删除,每当它被垃圾回收时,回调将被触发,我们将能够看到 WeakMap 如何发生变化 。
但是...垃圾收集是不可预测的,也没有官方的方法来触发它,因此为了测试,我们将定期生成一堆对象并将它们保存在内存中 。以下是整个脚本:
(async () => { const listMap = new WeakMap(); // Stick each item in a WeakMap. document.querySelectorAll('li').forEach((node) => {listMap.set(node, node.id); }); const registry = new FinalizationRegistry((heldValue) => {// Garbage collection has happened!console.log('After collection:', heldValue); }); registry.register(document.getElementById('item2'), listMap);console.log('Before collection:', listMap); // Remove node, freeing up reference! document.getElementById('item2').remove();// Periodically create a bunch o' objects to trigger collection.const objs = [];while (true) {for (let i = 0; i < 100; i++) {objs.push(...new Array(100));}await new Promise((resolve) => setTimeout(resolve, 10)); }})();在发生任何事情之前,WeakMap 如预期的那样包含三个项 。但是在从DOM中删除第二项并进行垃圾收集之后,它看起来有点不同
 
Maps与WeakMaps在DOM节点管理中的妙用

文章插图
 
由于节点引用在DOM中不再存在,整个条目已从 WeakMap 中删除,从而释放了更多的内存 。这是一个很 nice 功能,有助于使环境的内存更加整洁 。




推荐阅读