Nat*_*ong 32 javascript dom javascript-events
(注意:我在下面使用jQuery,但问题实际上是一般的Javascript问题.)
假设我有一个div#formsection使用AJAX反复更新其内容的内容,如下所示:
var formSection = $('div#formsection');
var newContents = $.get(/* URL for next section */);
formSection.html(newContents);
Run Code Online (Sandbox Code Playgroud)
每当我更新这个div时,我会触发一个自定义事件,它将事件处理程序绑定到一些新添加的元素,如下所示:
// 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 */});
Run Code Online (Sandbox Code Playgroud)
所以:我将事件处理程序绑定到某些DOM节点,然后删除这些DOM节点并插入新节点(html()这样做)并将事件处理程序绑定到新的DOM节点.
我的事件处理程序是否与它们绑定的DOM节点一起被删除?换句话说,当我加载新的部分时,很多无用的事件处理程序堆积在浏览器内存中,等待不再存在的DOM节点上的事件,或者当它们的DOM节点被删除时它们被清除了吗?
奖金问题:如何自己测试?
Moo*_*Goo 22
事件处理函数受其他变量的垃圾收集.这意味着当解释器确定没有可能获得对函数的引用的方法时,它们将从内存中删除.但是,简单地删除节点并不能保证垃圾收集.例如,获取此节点和关联的事件处理程序
var node = document.getElementById('test');
node.onclick = function() { alert('hai') };
Run Code Online (Sandbox Code Playgroud)
现在让我们从DOM中删除节点
node.parentNode.removeChild(node);
Run Code Online (Sandbox Code Playgroud)
所以node将不再在您的网站上可见,但它显然仍然存在于内存中,事件处理程序也是如此
node.onclick(); //alerts hai
Run Code Online (Sandbox Code Playgroud)
只要node仍可以某种方式访问引用,它的相关属性(其中onclick一个)将保持不变.
现在让我们尝试一下,不要创建一个悬空变量
document.getElementById('test').onclick = function() { alert('hai'); }
document.getElementById('test').parentNode.removeChild(document.getElementById('test'));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,似乎没有其他方法可以访问DOM节点#test,因此当运行垃圾收集周期时,onclick应该从内存中删除处理程序.
但这是一个非常简单的案例.Javascript使用闭包可能会极大地复杂化垃圾收集性的确定.让我们尝试将稍微复杂的事件处理函数绑定到onclick
document.getElementById('test').onclick = function() {
var i = 0;
setInterval(function() {
console.log(i++);
}, 1000);
this.parentNode.removeChild(this);
};
Run Code Online (Sandbox Code Playgroud)
因此,当您单击#test时,元素将立即被删除,但是一秒钟之后,之后每秒,您将看到一个增加的数字打印到您的控制台.该节点被删除,并且不可能进一步引用它,但似乎它的一部分仍然存在.在这种情况下,事件处理函数本身可能不会保留在内存中,但它创建的范围是.
所以答案我猜是; 这取决于.如果存在对已删除DOM节点的悬空可访问引用,则它们的关联事件处理程序仍将与其余属性一起驻留在内存中.即使不是这种情况,事件处理程序函数创建的作用域可能仍在使用中并且在内存中.
在大多数情况下(并且高兴地忽略IE6)最好只相信垃圾收集器来完成它的工作,毕竟Javascript不是C. 但是,在最后一个示例的情况下,编写某种类型的析构函数来隐式关闭功能非常重要.
当从DOM中删除元素时,jQuery竭尽全力避免内存泄漏.只要您使用jQuery删除DOM节点,就应该通过jQuery处理事件处理程序和额外数据的删除.我强烈建议阅读John Resig的JavaScript忍者的秘密,因为他详细介绍了不同浏览器中的潜在泄漏以及jQuery等JavaScript库如何解决这些问题.如果您不使用jQuery,则在删除DOM节点时,您必须担心通过孤立事件处理程序泄漏内存.
| 归档时间: |
|
| 查看次数: |
9937 次 |
| 最近记录: |