目前浏览器中使用闭包和(jQuery)DOM事件会导致内存泄漏?

3

我新接触JavaScript,似乎遇到了一些跟踪内存泄漏的问题。由于代码相当复杂,我已经将其缩小到一个部分,似乎是引起内存泄漏的原因。我将发布一个不同的示例,将其简单化,但会导致相同的问题(只是小得多)。

代码示例

基本上,我有一些动态构建HTML和附加事件到HTML的代码。 HTML会在每个AJAX请求中重新构建。这一切第一次都工作得很好,但是在每个AJAX请求之后,浏览器内存增加(不总是相等)!在JSFiddle上多次点击运行,就可以重现这个问题,并观察浏览器的内存。我的假设是创建的闭包永远不会被垃圾回收,但我不确定?如果是这种情况,有没有更好的方法来避免闭包而不会引起任何问题?

这在FF8、最新版的Chrome和IE 8中发生。很可能所有其他浏览器也是如此 - 这只是我测试过的。

我在代码中放了一些注释应该会有帮助。

谢谢!

编辑: 好的,经过使用sIEve进行更多研究,我发现每次AJAX调用时DOM节点数量会增加一倍。我已更新示例以模拟此情况。那么我的问题是,为什么在调用jQuery empty或remove函数后DOM元素没有被垃圾回收?我还循环遍历了stuff中的元素,解除事件处理程序并将每个DOM元素的js引用设置为null,但没有影响...

代码示例


有些HTML / DOM-JS内存问题与IE6等存在(问题是DOM具有一个内存模型,而JS引擎具有另一个内存模型,并且尝试在两者之间解决),尽管我认为这已经基本解决了...不确定现代浏览器中是否存在任何当前的“陷阱”。 - user166390
我无法在最新的Chrome上重现这个问题 :/ - Martin.
可能需要说明Chrome的“最新版本”是什么,因为它不总是相同的。此外,请指定所使用的jQuery版本。:) 旧版本的jQuery存在事件内存泄漏问题。 - user166390
@pst 抱歉,我正在使用jQuery 1.7.1。 我认为这应该是jsfiddle示例中包含的。 我不确定Chrome版本是否相关。 我想说的是问题似乎不是特定于浏览器的。 - user1084440
5个回答

3
这与DOM的GC和JavaScript的GC不兼容有关。基本意思是,如果某个东西被DOM引用,JS的GC可能不会销毁它,反之亦然。这个想法可能已经过时了,因为它出现在几代旧的浏览器中Crockford的书中。
我看到这里有几个潜在的问题,可能特定于JS Fiddle但也可能不是:
- 分配F是否必要? - 你每次一个接一个地创建大量的DOM元素, - 你每次运行都重新创建F,所以问题更可能是在DOM的GC而不是JavaScript的GC中。 - JavaScript的GC是标记和清除扫描程序,这意味着它是“懒惰”的。你可以在脚本中看到这一点——如果你运行它十次,内存使用率会急剧上升,但最终废弃的对象会被垃圾回收,内存使用率会降下来。 - 你需要担心的闭包是分配给click元素的,但你在这里没有使用闭包。
但我没有发现任何真正的问题,几分钟后,我的内存使用率就恢复正常了。
简而言之,你没有内存泄漏(至少没有紧迫的),你的JS解释器的GC只是懒惰。你放弃了许多DOM元素,这不好,并且是你的内存飙升的原因,但这只是一个短期的性能损失,而不是长期的页面加载问题。

1

程序分配内存,看到内存使用量增加,然后在释放内存时不会改变,这并不罕见。这是底层操作系统管理内存的结果,不一定是问题或引起担忧的原因。通常情况下,您应该使用其他工具来查找程序中的内存泄漏(无论是本地代码还是浏览器中的代码),而不是依赖跟踪整个进程统计信息的系统工具。


0

你需要小心仅仅查看浏览器的内存使用情况。更准确的测试方法是多次运行代码,然后查看浏览器的内存使用情况,再运行多次并比较新的数字。

通常情况下,浏览器的行为不仅仅反映了JavaScript的使用。因此,它的内存使用情况可能会波动,而不一定是你的代码有内存泄漏。


0

有一个技巧可以减少/避免内存泄漏,至少在IE中是这样。

你可以尝试一下,看看内存是否比你当前的方法更快地释放。
它是先将HTML插入到DOM中,然后再附加事件。


0

我和ShaggyFrog的想法一致。你可以通过删除本地变量并在使用完appendUs数组后手动清空它来减少内存分配。在Chrome中,我看到每次运行脚本时内存分配跳高了800KB-1MB。按照上述方法对代码进行小改动后,每次运行额外的内存分配量减少到400-500KB(通过任务管理器手动观察平均值)。

话虽如此,这种行为可能只是Windows和/或Chrome及其内存管理的问题。在让JSFiddle页面闲置一段时间后,Chrome的内存使用情况恢复到我开始运行你的示例之前的水平。某种垃圾回收最终会发生,只是可能不像你期望的那样快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接