只有页面的 DOM 树或 JavaScript 代码不再引用 DOM 节点时,DOM 节点才会被作为垃圾进行回收。 如果某个节点已从 DOM 树移除,但某些 JavaScript 仍然引用它,我们称此节点为“已分离”,已分离的 DOM 节点是内存泄漏的常见原因。
同理,调出调试面板,点击Memory,然后选择Heap Snapshot,然后点击进行录制。录制完成后,选中录制结果,在 Class filter 文本框中键入 Detached,搜索已分离的 DOM 树。
以这段代码为例:
点击几下,然后记录。可以得到以下信息:
旧版的面板,还会有颜色标注,黄色的对象实例表示它被JS代码引用,红色的对象实例表示被黄色节点引用的游离节点。上图是新版本的,不会有颜色标识。但是还是可以一个个来看,如上图,点开节点,可以看到下面的引用信息,上面可以看出,有个HTMLUListElement(ul节点)被window.detachedNodes引用。再结合代码,原来是没有加var/let/const声明,导致其成了全局变量,所以DOM无法释放。
按函数调查内存分配
打开面板,点击JavaScript Profiler,如果没看到这个选项,你可以点调试面板右上角的三个点,选择more tools,然后选择。
ps: chrome 旧版的浏览器,这个功能在 Profiles 里面,点Record Allocation Profile即可.
操作步骤:点start->在页面进行你要检测的操作->点stop。
DevTools 按函数显示内存分配明细。默认视图为 Heavy (Bottom Up),将分配了最多内存的函数显示在最上方,还有函数的位置,你可以看看是哪些函数占用内存较多。 避免内存泄漏的方法
少用全局变量,避免意外产生全局变量
使用闭包要及时注意,有Dom元素的引用要及时清理。
计时器里的回调没用的时候要记得销毁。
为了避免疏忽导致的遗忘,我们可以使用 WeakSet 和 WeakMap结构,它们对于值的引用都是不计入垃圾回收机制的,表示这是弱引用。
举个例子:
这种情况下,一旦消除对该节点的引用,它占用的内存就会被垃圾回收机制释放。Weakmap 保存的这个键值对,也会自动消失。
基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。
参考资料极客时间《浏览器工作原理与实践》
https://developers.google.com/web/tools/chrome-devtools/memory-problems?hl=zh-cn
最后欢迎加我微信(winty230),拉你进技术群,长期交流学习...
欢迎关注「前端Q」,认真学前端,做个有专业的技术人...