欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 18:26:24
...

本文翻译自:If a DOM Element is removed, are its listeners also removed from memory?

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


#1楼

参考:https://stackoom.com/question/qZ7J/如果删除了DOM元素-是否还将其侦听器也从内存中删除了


#2楼

Yes, the garbage collector will remove them as well. 是的,垃圾收集器也会将其删除。 Might not always be the case with legacy browsers though. 但是,旧版浏览器可能并非总是如此。


#3楼

Modern browsers 现代浏览器

Plain JavaScript 纯JavaScript

If a DOM element which is removed is reference-free (no references pointing to it) then yes - the element itself is picked up by the garbage collector as well as any event handlers/listeners associated with it. 如果删除的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.

However; 然而; if there are references that still point to said element, the element and its event listeners are retained in memory. 如果存在仍然指向该元素的引用,则该元素及其事件侦听器将保留在内存中。

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的

It would be fair to assume that the relevant methods in jQuery (such as remove() ) would function in the exact same way (considering remove() was written using removeChild() for example). 假设jQuery中的相关方法(例如remove() )将以完全相同的方式起作用(考虑到remove()是使用removeChild()编写的removeChild() ,这是很公平的。

However, this isn't true ; 但是, 这不是真的 the jQuery library actually has an internal method (which is undocumented and in theory could be changed at any time) called cleanData() (here is what this method looks like ) which automatically cleans up all the data/events associated with an element upon removal from the DOM (be this via. remove() , empty() , html("") etc). jQuery库实际上有一个内部方法(该方法未公开,理论上可以随时更改),称为cleanData() (此方法的外观如下 ), 该方法在删除时会自动清除与元素关联的所有数据/事件从DOM中获取(通过remove()empty()html("")等)。


Older browsers 较旧的浏览器

Older browsers - specifically older versions of IE - are known to have memory leak issues due to event listeners keeping hold of references to the elements they were attached to. 已知较旧的浏览器(尤其是IE的较旧版本)会出现内存泄漏问题,这是因为事件侦听器保留了对其所附加元素的引用。

If you want a more in-depth explanation of the causes, patterns and solutions used to fix legacy IE version memory leaks, I fully recommend you read this MSDN article on Understanding and Solving Internet Explorer Leak Patterns. 如果您想更深入地解释用于解决旧版IE版本内存泄漏的原因,模式和解决方案,我完全建议您阅读此MSDN文章,了解和解决Internet Explorer泄漏模式。

A few more articles relevant to this: 一些与此相关的文章:

Manually removing the listeners yourself would probably be a good habit to get into in this case (only if the memory is that vital to your application and you are actually targeting such browsers). 在这种情况下,您自己可以手动删除监听器,这可能是一个好习惯(仅当内存对于您的应用程序至关重要,而您实际上是针对此类浏览器的时候)。


#4楼

regarding jQuery: 关于jQuery:

the .remove() method takes elements out of the DOM. .remove()方法将元素移出DOM。 Use .remove() when you want to remove the element itself, as well as everything inside it. 要删除元素本身以及其中的所有内容时,请使用.remove()。 In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed. 除了元素本身之外,所有绑定的事件和与元素相关联的jQuery数据都将被删除。 To remove the elements without removing data and events, use .detach() instead. 要删除元素而不删除数据和事件,请改用.detach()。

Reference: http://api.jquery.com/remove/ 参考: http : //api.jquery.com/remove/

jQuery v1.8.2 .remove() source code: 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;
}

apparently jQuery uses node.removeChild() 显然,jQuery使用node.removeChild()

According to this : https://developer.mozilla.org/en-US/docs/DOM/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.

ie event listeners might get removed, but node still exists in memory. 即事件监听器可能会被删除,但node仍存在于内存中。


#5楼

Don't hesitate to watch heap to see memory leaks in event handlers keeping a reference to the element with a closure and the element keeping a reference to the event handler. 不要犹豫地观看堆,以查看事件处理程序中的内存泄漏,该事件处理程序使用闭包保留对该元素的引用,而该元素保留对事件处理程序的引用。

Garbage collector do not like circular references. 垃圾收集器不喜欢循环引用。

Usual memory leak case: admit an object has a ref to an element. 通常的内存泄漏情况:承认对象具有对元素的引用。 That element has a ref to the handler. 该元素具有对处理程序的引用。 And the handler has a ref to the object. 处理程序具有对该对象的引用。 The object has refs to a lot of other objects. 该对象引用了许多其他对象。 This object was part of a collection you think you have thrown away by unreferencing it from your collection. 该对象是您认为已从集合中取消引用它而丢弃的集合的一部分。 => the whole object and all it refers will remain in memory till page exit. =>整个对象及其引用的所有对象将保留在内存中,直到页面退出。 => you have to think about a complete killing method for your object class or trust a mvc framework for example. =>您必须为您的对象类考虑一种完整的杀死方法,或者例如信任mvc框架。

Moreover, don't hesitate to use the Retaining tree part of Chrome dev tools. 此外,请不要犹豫使用Chrome开发人员工具的“保留树”部分。


#6楼

Regarding jQuery , the following common methods will also remove other constructs such as data and event handlers: 关于jQuery ,以下常用方法还将删除其他构造,例如数据和事件处理程序:

remove() 去掉()

In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed. 除了元素本身之外,所有绑定的事件和与元素相关联的jQuery数据都将被删除。

empty() 空()

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves. 为了避免内存泄漏,jQuery在删除元素本身之前先从子元素中删除其他构造,例如数据和事件处理程序。

html() html()

Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content. 此外,在用新内容替换那些元素之前,jQuery从子元素中删除了其他构造,例如数据和事件处理程序。