Javascript 内存泄漏:分离的 DOM 树

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16901759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 06:24:50  来源:igfitidea点击:

Javascript Memory Leaks: Detached DOM tree

javascriptjquerygoogle-chrome-devtools

提问by Joseph Caruana

I have noticed that the memory of the browser starts increasing whilst I am in a form (this is noticeable from the task manager). In IE 9, this goes easily over 500MB after some usage, whilst chrome is more resilient (goes to 200MB using same test).

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

I am using the chrome developer tools to debug this issue. I have noticed that there is a large number of Detached DOM tree:

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

detached dom tree screenshot

分离的 dom 树截图

I am assuming that this can confirm that there is a memory leak. Would that be correct? Secondly, I would need to find out how to identify the root cause of the problem. I know that you should use the retaining tree to identify what is stopping those items from being reclaimed. But I cannot find out how to use the retaining tree. For example, what does the retaining tree in the above screenshot mean please?

我假设这可以确认存在内存泄漏。那会是正确的吗?其次,我需要找出如何确定问题的根本原因。我知道您应该使用保留树来确定是什么阻止了这些项目被回收。但我不知道如何使用保留树。例如,上面截图中的保留树是什么意思?

Any assistance would be greatly appreciated.

任何帮助将不胜感激。

采纳答案by Robin Maben

There are many considerations to keep in mind when you write code that references DOM elements. But it all basically boils down to a couple of simple points -

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

a. Within your local functions always clear the reference

一个。在您的本地函数中,始终清除引用

var menu = $('body #menu');
// do something with menu
 .
 .
 .
 menu = null;

b. Never store references as part of element data .data()

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

c. Try not to use DOM references inside closures/inline handlers, instead pass identifiers

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!             
      }
    }

Yes, one can argue that searching elements can slow the page down, but the delay is very minimal when compared to the performance hit a huge heap causes esp. in large single page applications. Hence, #3 should be used only after weighing the pros and cons. (It did help significantly in my case)

是的,有人可能会争辩说搜索元素会减慢页面速度,但与性能命中一个巨大的堆导致的延迟相比,延迟非常小。在大型单页应用程序中。因此,只有在权衡利弊后才应使用#3。(在我的情况下它确实有很大帮助)

UPDATE

更新

d. Avoid anonymous functions - Naming your event handlers and local functions will help you a lot while profiling/looking at heap snapshots.

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

回答by loislo

Looks like your code creates many DOM subtrees and keeps references to it from javascript. You need to select an element from a Detached dom tree. According to the snapshot you should select Text element. And look into the retainers tree.

看起来您的代码创建了许多 DOM 子树并保留了来自 javascript 的引用。您需要从分离的 dom 树中选择一个元素。根据快照,您应该选择文本元素。并查看家臣树。

This tree shows you all the paths that keeps the object alive. At least one path, usually the shortest one, will lead you to the window object. If you familiar with the code then you may easily find the object in that path that has to be deleted but it doesn't. There can be many such objects in the path. The object with the smallest distance is more interesting.

这棵树向您显示了使对象保持活动状态的所有路径。至少有一条路径,通常是最短的路径,将引导您到 window 对象。如果您熟悉代码,那么您可能很容易在该路径中找到必须删除但没有删除的对象。路径中可以有很多这样的对象。距离最小的物体更有趣。