如果删除了 DOM 元素,其侦听器是否也从内存中删除了?

2022-08-29 23:27:11

如果删除了 DOM 元素,其侦听器是否也从内存中删除了?


答案 1

现代浏览器

纯 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库实际上有一个内部方法(它是未记录的,理论上可以随时更改)称为(这是此方法的样子),它在从DOM中删除时自动清理与元素相关的所有数据/事件(通过,等)。cleanData()remove()empty()html("")


较旧的浏览器

已知较旧的浏览器(特别是较旧版本的IE)由于事件侦听器保留对它们所附加到的元素的引用而存在内存泄漏问题。

如果您想更深入地了解用于修复旧版 IE 版本内存泄漏的原因、模式和解决方案,我完全建议您阅读这篇 MSDN 文章,了解和解决 Internet Explorer 泄漏模式。

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

在这种情况下,自己手动删除侦听器可能是一个好习惯(仅当内存对您的应用程序至关重要并且您实际上针对此类浏览器时)。


答案 2

关于jQuery:

.remove() 方法将元素从 DOM 中取出。如果要删除元素本身以及其中的所有内容,请使用 .remove()。除了元素本身之外,还将删除与元素关联的所有绑定事件和 jQuery 数据。若要删除元素而不删除数据和事件,请改用 .detach()。

参考资料: http://api.jquery.com/remove/

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()

据此:https://developer.mozilla.org/en-US/docs/DOM/Node.removeChild

The removed child node still exists in memory, but is no longer part of the DOM. You may reuse the removed node later in your code, via the oldChild object reference.

即事件侦听器可能会被删除,但仍存在于内存中。node