Javascript 如果删除了DOM元素,那么它的侦听器是否也从内存中删除?

Javascript 如果删除了DOM元素,那么它的侦听器是否也从内存中删除?,javascript,jquery,dom,memory,memory-leaks,Javascript,Jquery,Dom,Memory,Memory Leaks,如果删除DOM元素,它的侦听器也会从内存中删除吗?是的,垃圾收集器也会删除它们。但传统浏览器可能并不总是如此。现代浏览器 普通JavaScript 如果删除的DOM元素是无引用的(没有指向它的引用),则是-垃圾收集器以及与之关联的任何事件处理程序/侦听器将拾取该元素本身 var a = document.createElement('div'); var b = document.createElement('p'); // Add event listeners to b etc... a.a

如果删除DOM元素,它的侦听器也会从内存中删除吗?

是的,垃圾收集器也会删除它们。但传统浏览器可能并不总是如此。

现代浏览器 普通JavaScript

如果删除的DOM元素是无引用的(没有指向它的引用),则-垃圾收集器以及与之关联的任何事件处理程序/侦听器将拾取该元素本身

var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
b = null; 
// A reference to 'b' no longer exists 
// Therefore the element and any event listeners attached to it are removed.
但是,;如果仍有指向所述元素的引用,则该元素及其事件侦听器将保留在内存中

var a = document.createElement('div');
var b = document.createElement('p'); 
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b); 
// A reference to 'b' still exists 
// Therefore the element and any associated event listeners are still retained.
jQuery

可以公平地假设jQuery中的相关方法(例如
remove()
)将以完全相同的方式运行(例如,考虑到
remove()
是使用
removeChild()
编写的)

然而,这不是真的;jQuery库实际上有一个名为
cleanData()
)的内部方法(没有文档记录,理论上可以随时更改),它可以在从DOM中删除元素时自动清除与元素相关的所有数据/事件(可以通过
remove()
empty()
html(“
等)


旧浏览器 众所周知,较旧的浏览器(特别是IE的较旧版本)存在内存泄漏问题,原因是事件侦听器保留了对它们所附加到的元素的引用

如果您想更深入地解释用于修复旧版IE内存泄漏的原因、模式和解决方案,我完全建议您阅读

还有几篇与此相关的文章:

在这种情况下,手动删除侦听器可能是一个好习惯(只有当内存对应用程序非常重要,并且您实际上针对的是这样的浏览器时)。

关于jQuery:

.remove()方法从 多姆。如果要删除元素本身,也可以使用.remove() 就像里面的一切。除了元素本身,所有 与元素关联的绑定事件和jQuery数据将被删除。 要在不删除数据和事件的情况下删除元素,请使用.detach() 相反

参考:

jQuery v1.8.2
.remove()
源代码:

remove: function( selector, keepData ) {
    var elem,
        i = 0;

    for ( ; (elem = this[i]) != null; i++ ) {
        if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
            if ( !keepData && elem.nodeType === 1 ) {
                jQuery.cleanData( elem.getElementsByTagName("*") );
                jQuery.cleanData( [ elem ] );
            }

            if ( elem.parentNode ) {
                elem.parentNode.removeChild( elem );
            }
        }
    }

    return this;
}
显然jQuery使用的是
node.removeChild()

据此:,

删除的子节点仍然存在于内存中,但不再是DOM的一部分。稍后,您可以通过oldChild对象引用在代码中重用删除的节点。


ie事件侦听器可能会被删除,但
节点仍然存在于内存中。

请毫不犹豫地观察heap,查看事件处理程序中是否存在内存泄漏,该事件处理程序使用闭包保留对元素的引用,而元素保留对事件处理程序的引用

var a = document.createElement('div');
var b = document.createElement('p'); 
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b); 
// A reference to 'b' still exists 
// Therefore the element and any associated event listeners are still retained.
垃圾收集器不喜欢循环引用

常见内存泄漏情况: 允许对象具有对元素的引用。该元素具有对处理程序的引用。并且处理程序有一个对对象的引用。 该对象引用了许多其他对象。此对象是一个集合的一部分,您认为通过从集合中取消引用它而将其丢弃。 =>整个对象及其引用的所有内容将保留在内存中,直到页面退出。 =>您必须为您的对象类考虑一个完整的终止方法,或者信任一个mvc框架


此外,请毫不犹豫地使用Chrome开发工具的保留树部分。

关于
jQuery
,以下常用方法还将删除其他结构,如数据和事件处理程序:

除了元素本身之外,与元素关联的所有绑定事件和jQuery数据都将被删除

为了避免内存泄漏,jQuery在删除元素本身之前从子元素中删除其他结构,如数据和事件处理程序

此外,jQuery在用新内容替换子元素之前,会从子元素中删除其他构造(如数据和事件处理程序)


只是扩展其他答案

删除元素时不会删除委派事件处理程序。

$('body').on('click', '#someEl', function (event){
  console.log(event);
});

$('#someEL').remove(); // removing the element from DOM
现在检查:

$._data(document.body, 'events');

您只是增加了混淆——jQuery没有做任何简单的
removeChild
处理程序所不能做的事情。两者都会返回一个引用,您可以保留该引用以重新附加后者(在这种情况下,它显然会保留在内存中)或抛出方式(在这种情况下,它最终会被GC拾取并删除)?因为在前面的问题中,我可以发誓使用jquery删除DOM元素是有道理的。现在我的回答听起来像是我在解释事情,只是为了激发我的自尊心。嘿,您可以始终使用DownVoteA。根据jquery文档,当对元素使用remove()方法时,所有事件侦听器都将从内存中删除。这将影响其自身的元素和所有子节点。如果要将事件列表器保留在内存中,则应改为使用.detach()。当删除的元素将再次插入dom时非常有用。如果该元素包含子元素,它是否也会分离子元素上的事件列表项?@Lothre1-这仅在使用
remove
方法时有效。大多数情况下,DOM将被完全擦除。(比如涡轮连杆之类的)。我想知道如果我做
document.body.innerHTML='
,内存会受到什么影响……我需要的不仅仅是“个人经验”,更像是硬数据和测试,以及指向规范的链接,说明内存如何在文档中不再存在的节点上保持持久性,这一点太重要了,不能只相信某人的话而不提供证据:)@Lothre1谢谢-我已经深入挖掘了一些,并发现jQuery与