如何在没有内存泄漏的情况下删除DOM元素?

pod*_*eig 47 javascript jquery dom memory-leaks

我的JavaSript代码构建了一个LI元素列表.当我更新列表时,内存使用量会增长,永远不会下降.我在筛测试,则说明该浏览器会被认为是通过删除所有的元素$.remove()$.emptyjQuery的命令.

如何在没有内存泄漏的情况下删除DOM节点?

有关具体代码,请参阅我的其他问题.

Ran*_*Dev 45

DOM保留所有DOM节点,即使它们已从DOM树本身中删除,删除这些节点的唯一方法是进行页面刷新(如果将列表放入iframe,则刷新将不会如此明显)

否则,您可以等待问题变得糟糕,以至于浏览器垃圾收集器被强制执行(在此处讨论数百兆字节的未使用节点)

最佳实践是重用节点.

编辑:试试这个:

var garbageBin;
window.onload = function ()
    {
    if (typeof(garbageBin) === 'undefined')
        {
        //Here we are creating a 'garbage bin' object to temporarily 
        //store elements that are to be discarded
        garbageBin = document.createElement('div');
        garbageBin.style.display = 'none'; //Make sure it is not displayed
        document.body.appendChild(garbageBin);
        }
    function discardElement(element)
        {
        //The way this works is due to the phenomenon whereby child nodes
        //of an object with it's innerHTML emptied are removed from memory

        //Move the element to the garbage bin element
        garbageBin.appendChild(element);
        //Empty the garbage bin
        garbageBin.innerHTML = "";
        }
    }
Run Code Online (Sandbox Code Playgroud)

要在您的上下文中使用它,您可以这样做:

discardElement(this);
Run Code Online (Sandbox Code Playgroud)

  • 我不知道"DOM保留所有DOM节点,即使它们已经从DOM树本身删除了"你的意思是$ .remove()函数什么都不做? (9认同)
  • 这个答案令人困惑和含糊不清.它说页面刷新是删除节点的"唯一方法",但它也暗示浏览器的垃圾收集将释放这些节点的内存.如果为true,则刷新不是"唯一"方式.而且,从开发人员的角度来看,应该没有区分可以被垃圾收集的对象和已经被垃圾收集的对象 - 这是自动内存管理的全部要点 - 当GC运行时应该是不透明的用户. (8认同)
  • 在sIEve中测试后,我可以说它有助于删除垃圾节点.但是当我在IE8和FF中进行测试时,无论如何内存使用量都在增长.安德鲁,appendChild有什么作用?将节点移动到垃圾div?我应该在discadElement()之前运行$ .unbind()吗? (2认同)
  • 是否需要将垃圾箱添加到文档的正文中? (2认同)
  • "DOM保留所有DOM节点"是否意味着实现DOM规范的浏览器实际上会存储对DOM树之外的节点的引用,或者只是那些节点将在内存中挂起,直到下一次垃圾收集器运行?答案意味着后者,但是如果它们能够被垃圾收集,那么这些节点在任何意义上都不会被"保留". (2认同)

FK8*_*K82 13

这更像是一个FYI,而不是一个真正的答案,但它也很有趣.

来自W3C DOM核心规范(http://www.w3.org/TR/DOM-Level-2-Core/core.html):

Core DOM API旨在与各种语言兼容,包括通用用户脚本语言和主要由专业程序员使用的更具挑战性的语言.因此,DOM API需要跨多种内存管理原理进行操作,从不公开内存管理的语言绑定到用户,通过提供显式构造函数但提供自动垃圾收集机制的那些(特别是Java).将未使用的内存回收给那些通常需要程序员明确分配对象内存,跟踪它的使用位置并明确释放它以供重用的那些(特别是C/C++).为了确保跨这些平台的API一致,DOM根本不解决内存管理问题,而是将这些问题留给实现.DOM API(对于ECMAScript和Java)定义的显式语言绑定都不需要任何内存管理方法,但是其他语言(尤其是C或C++)的DOM绑定可能需要这样的支持.这些扩展将由那些使DOM API适应特定语言的人负责,而不是DOM工作组.

换句话说:内存管理留给各种语言的DOM规范实现.你必须在javascript中查看DOM实现的文档,找出从内存中删除DOM对象的任何方法,这不是一个黑客攻击.(关于该主题,MDC网站上的信息很少.)


作为一个注释jQuery#removejQuery#empty:我可以告诉他们这些方法除了Object从DOM中node删除s或node从中删除DOM 之外还做了什么document.它们只删除当然并不意味着没有分配给这些对象的内存(即使它们document不再存在).

编辑:上面的段落是多余的,因为显然jQuery不能创造奇迹并解决使用过的浏览器的DOM实现.

  • 来自jQuery .remove()API:"...除了元素本身之外,还删除了与元素关联的所有绑定事件和jQuery数据.要删除元素而不删除数据和事件,请改用.detach()." (2认同)

Ski*_*ick 8

你删除了任何事件监听器吗?这可能会导致内存泄漏.

  • 我认为当你执行element.remove()时,jQuery会自动删除事件处理程序,不是吗? (2认同)