Javascript内存泄漏:分离的DOM树

Jos*_*ana 32 javascript jquery google-chrome-devtools

我注意到浏览器的内存在我处于一种形式时开始增加(这在任务管理器中很明显).在IE 9中,在使用一段时间后,这很容易超过500MB,而chrome则更具弹性(使用相同的测试可达到200MB).

我正在使用chrome开发人员工具来调试此问题.我注意到有大量的Detached DOM树:

独立的dom树截图

我假设这可以确认存在内存泄漏.这是对的吗?其次,我需要找出如何确定问题的根本原因.我知道您应该使用保留树来识别阻止这些物品被回收的原因.但我无法找到如何使用保留树.例如,上面屏幕截图中的保留树是什么意思?

任何帮助将不胜感激.

Rob*_*ben 27

编写引用DOM元素的代码时,请记住许多注意事项.但这一切基本上归结为几个简单点 -

一个.在您的本地功能中始终清除参考

var menu = $('body #menu');
// do something with menu
 .
 .
 .
 menu = null;
Run Code Online (Sandbox Code Playgroud)

湾 永远不要将引用存储为元素数据的一部分.data()

C.尽量不要在闭包/内联处理程序中使用DOM引用,而是传递标识符

    function attachClick(){
      var someDiv = $('#someDiv');

      someDiv.click(function(){
         var a = someDiv....;
         //Wrong. Instead of doing this..
      });


      someDiv.click(function(){
         var a = $('#someDiv');
         //Pass the identifier/selector and then use it to find the element
      });       


      var myFunc = function(){
         var a = someDiv;
         //using a variable from outside scope here - big DON'T!             
      }
    }
Run Code Online (Sandbox Code Playgroud)

是的,人们可以争辩说,搜索元素可以减慢页面速度,但与性能影响相比,延迟是非常小的.在大型单页面应用程序中.因此,只有在权衡利弊后才能使用#3.(在我的案例中它确实有很大帮助)

UPDATE

d.避免使用匿名函数 - 在分析/查看堆快照时,命名事件处理程序和本地函数将对您有所帮助.

  • @pebbl:我查看了我的代码.你是对的.我的意思是闭包而不是简单地将它们传递给方法.修正了上面的例子. (2认同)
  • 我不同意这些技巧。(a)是不必要的;只要保留了作用域(例如,当您离开本地函数时),只要没有剩余的引用引用,它将被清理。(b)如果您要负责存储多少引用,那是很好的做法;存放它们的位置都没有关系。(c)同一件事。只需对您存储了多少引用负责。使用更高范围的变量很好,并且可以提高性能。更大的问题是您可能会创建元素并分离它们,而不是实际删除它们。 (2认同)
  • 还要注意附加到DOM元素的任何事件侦听器,并且在分离DOM元素时不会将其删除 (2认同)