使用适当的GC删除DOM节点(无泄漏)

vsy*_*ync 7 javascript garbage-collection memory-leaks google-chrome-devtools

问题

添加节点,同时从DOM中删除旧节点,不会丢弃内存中的旧节点.(至少不是所有人,没有明显的理由).

如何看待这种情况

(你已经知道了,但无论如何..)
右键单击输出区域并使用Chrome 开发人员工具进行检查.单击时间轴选项卡,然后单击左上角的圆圈(点)开始录制.

现在点击body元素,它将每隔300ms 开始添加和删除项目
(删除的节点应该被垃圾收集).

停止录制,将数据采样区域扩展到最大,您将在屏幕的下半部分看到绿色的节点.预期的图形将上下移动(其中下降意味着GC已正确丢弃节点).

测试页面

这2个测试页面非常原始.当然,在现实生活中,开发人员使用生成大量文本的模板,这些模板应转换为DOM并注入页面,因此内存中的实时DOM节点数应保持较低,并且必须丢弃已删除的节点.

与jQuery - http://jsbin.com/lamigucuqogi/2/edit - 大约40秒后,GC变得疯狂并停止收集被删除的节点,这会导致通货膨胀.

在此输入图像描述

朴素的方式 - http://jsbin.com/riref/2/edit - 似乎节点没有以令人满意的速度被移除,并且数量不断增长和增长...

在此输入图像描述

为什么会发生这种情况,如何正确地删除NODES以便不会发生通货膨胀?

joe*_*ews 5

你误会了.如果您将示例保持运行很长一段时间,那么使用Dev Tools时间轴中的垃圾箱图标强制进行垃圾收集,您将观察到节点已被释放.

与任何其他JavaScript对象一样,当DOM节点无法从GC Roots访问时,它们就有资格使用GC .如果您不保留对已删除节点的任何其他引用(例如,在数组中),则从主文档中删除它们后将无法访问它们.

但是,它们不会立即被垃圾收集 - GC运行可能需要一些时间,在此期间主浏览器线程被阻止,因此它只会定期运行.您所看到的是JavaScript引擎决定不运行垃圾收集器的时期.您不应该担心这一点 - 您的代码确实允许垃圾收集器在最终运行时释放内存.

强烈推荐观看 - Addy Osmani的内存管理大师班.

  • 你的前提似乎是删除的节点不是垃圾收集.这可以通过触发手动GC事件来测试.执行此操作时,已删除的节点_are_已收集.你的代码非常好.你不应该担心_when_ JS引擎决定使用GC,只是你的代码使它能够在运行时有效地释放内存.这是一个答案,因为它解释了问题不是由您的代码引起的,这可能会在将来解决另一个用户的类似问题. (2认同)