答案 0 :(得分:0)
没有first image暗示强烈的内存泄漏。
JS堆图(蓝图)并不那么简单。为了与最佳实践保持一致,第一次尝试实际上是垃圾收集。随着录制的进行,您可以看到JS堆大小激增。这是很自然和期望的:JavaScript代码创建DOM节点并在创建一百万个字符的字符串时执行大量工作。这里的关键是JS堆的结束高于它的开始(这里的“开始”是强制垃圾收集之后的点)。在现实世界中,如果您看到这种增加JS堆大小或节点大小的模式,则可能意味着内存泄漏。
摘自here。
尝试做以下几件事:
关于如何处理JS中的内存管理,您可能会阅读此article。
有一个垃圾清理,浏览器经常在一定限制后安排。在检查时间线时你会发现有Major GC collected
。现在编译器清理那些无法访问的节点。不知何故,在大量使用递归或闭包的情况下,仍然存在一些或其他仍然保持变量的链接。
答案 1 :(得分:0)
第一个肯定是内存泄漏。第二个看起来与使用setInterval
/ setInterval
时出现的锯齿图案相同。从技术上讲,后者不是内存泄漏,但要小心你如何使用它们。看一下递归超时和间隔之间的差异,因为间隔可以允许它应该在一个间隔结束后但在第一个回调完成执行之前执行它应该运行的回调。
一些注意事项:
对封闭非常小心,尤其是与其周围功能相比的范围和背景
可以通过循环引用来捕获函数中的大变量,例如:以下内容泄漏str
,因为它位于logSomething
的本机范围对象中:
function leaks() {
let str = 'a'.repeat(Math.pow(10, 8)); // 1 billion
const referenceStr = () => str === 'b'.repeat(Math.pow(10, 8));
const logSomething = () => console.log('leaking...');
referenceStr();
setInterval(logSomething, 60 * 1000);
}
setInterval(leaks, 60 * 1000);
同样,在DOM和javascript之间进行循环引用。此函数泄漏str
,因为body
包含对DOM的引用,其onclick
处理程序保存对javascript世界的引用,该引用还包含对str
的引用。本机范围对象,body
永远不会被取消,也可以将DOM元素保留在javascript世界中。
(function leaks() {
let str = 'a'.repeat(Math.pow(10, 8));
let body = document.body;
body.onclick = () => alert(str);
})();
setInterval(() => document.body.click(), 60 * 1000);
始终删除事件处理程序 使用事件处理程序删除对象而不删除所有对象 事先可能会导致泄密