DOM 节点上的事件处理程序是否会随节点一起删除? [英] Do events handlers on a DOM node get deleted with the node?

查看:45
本文介绍了DOM 节点上的事件处理程序是否会随节点一起删除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(注意:我在下面使用 jQuery,但问题确实是一个通用的 Javascript 问题.)

(Note: I'm using jQuery below, but the question is really a general Javascript one.)

假设我有一个 div#formsection,其内容使用 AJAX 重复更新,如下所示:

Say I've got a div#formsection whose contents are repeatedly updated using AJAX, like this:

var formSection = $('div#formsection');
var newContents = $.get(/* URL for next section */);
formSection.html(newContents);

每当我更新这个 div 时,我触发一个自定义事件,它将事件处理程序绑定到一些新添加的元素,如下所示:

Whenever I update this div, I trigger a custom event, which binds event handlers to some of the newly-added elements, like this:

// When the first section of the form is loaded, this runs...
formSection.find('select#phonenumber').change(function(){/* stuff */});

...

// ... when the second section of the form is loaded, this runs...
formSection.find('input#foo').focus(function(){/* stuff */});

所以:我将事件处理程序绑定到一些 DOM 节点,然后删除这些 DOM 节点并插入新节点(html() 这样做)并将事件处理程序绑定到新的 DOM 节点.

So: I'm binding event handlers to some DOM nodes, then later, deleting those DOM nodes and inserting new ones (html() does that) and binding event handlers to the new DOM nodes.

我的事件处理程序是否与它们绑定的 DOM 节点一起被删除? 换句话说,当我加载新部分时,是否有很多无用的事件处理程序堆积在浏览器内存中,等待对于不再存在的 DOM 节点上的事件,或者当它们的 DOM 节点被删除时它们是否被清除?

Are my event handlers deleted along with the DOM nodes they're bound to? In other words, as I load new sections, are lots of useless event handlers piling up in the browser memory, waiting for events on DOM nodes that no longer exist, or are they cleared out when their DOM nodes are deleted?

额外问题:如何自己测试?

推荐答案

事件处理函数受制于与其他变量相同的垃圾收集.这意味着当解释器确定没有可能的方法获得对函数的引用时,它们将从内存中删除.然而,简单地删除一个节点并不能保证垃圾收集.例如,拿这个节点和关联的事件处理程序

Event handler functions are subject to the same Garbage Collection that other variables are. That means they will be removed from memory when the interpreter determines that there is no possible means to obtain a reference to the function. Simply deleting a node however does not guarantee garbage collection. For instance, take this node and associated event handler

var node = document.getElementById('test');
node.onclick = function() { alert('hai') };

现在让我们从 DOM 中删除节点

Now lets remove the node from the DOM

node.parentNode.removeChild(node);

所以 node 将不再在您的网站上可见,但它显然仍然存在于内存中,事件处理程序也是如此

So node will no longer be visible on your website, but it clearly still exists in memory, as does the event handler

node.onclick(); //alerts hai

只要对 node 的引用仍然可以以某种方式访问​​,它的关联属性(其中 onclick 是其中之一)将保持不变.

As long as the reference to node is still accessible somehow, it's associated properties (of which onclick is one) will remain intact.

现在让我们在不创建悬空变量的情况下尝试

Now let's try it without creating a dangling variable

document.getElementById('test').onclick = function() { alert('hai'); }

document.getElementById('test').parentNode.removeChild(document.getElementById('test'));

在这种情况下,似乎没有其他方法可以访问 DOM 节点 #test,因此当运行垃圾回收周期时,应该从内存中删除 onclick 处理程序.

In this case, there seems to be no further way to access the DOM node #test, so when a garbage collection cycle is run, the onclick handler should be removed from memory.

但这是一个非常简单的案例.Javascript 对闭包的使用会使垃圾收集能力的确定变得非常复杂.让我们尝试将稍微复杂的事件处理函数绑定到 onclick

But this is a very simple case. Javascript's use of closures can greatly complicate the determination of garbage collectability. Lets try binding a slightly more complex event handler function to onclick

document.getElementById('test').onclick = function() {
  var i = 0;
  setInterval(function() {
    console.log(i++);
  }, 1000);

  this.parentNode.removeChild(this);
};

因此,当您单击 #test 时,该元素将立即被删除,但是一秒后,之后每一秒,您都会看到一个递增的数字打印到您的控制台.该节点被移除,无法进一步引用它,但它的一部分似乎仍然存在.在这种情况下,事件处理函数本身可能不会保留在内存中,而是它创建的范围.

So when you click on #test, the element will instantly be removed, however one second later, and every second afterwards, you will see an incremented number printed to your console. The node is removed, and no further reference to it is possible, yet it seems parts of it remain. In this case the event handler function itself is likely not retained in memory but the scope it created is.

所以我猜的答案是;这取决于.如果存在对已删除 DOM 节点的悬空、可访问引用,则其关联的事件处理程序及其其余属性仍将驻留在内存中.即使情况并非如此,事件处理程序函数创建的作用域可能仍在使用中并在内存中.

So the answer I guess is; it depends. If there are dangling, accessible references to deleted DOM nodes, their associated event handlers will still reside in memory, along with the rest of their properties. Even if this is not the case, the scope created by the event handler functions might still be in use and in memory.

在大多数情况下(并且很高兴地忽略 IE6),最好只相信垃圾收集器来完成它的工作,Javascript 毕竟不是 C.然而,在像最后一个例子这样的情况下,编写某种析构函数来隐式关闭功能是很重要的.

In most cases (and happily ignoring IE6) it is best to just trust the Garbage Collector to do its job, Javascript is not C after all. However, in cases like the last example, it is important to write destructor functions of some sort to implicitly shut down functionality.

这篇关于DOM 节点上的事件处理程序是否会随节点一起删除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆