如果删除元素,是否必须从DOM中清除事件?

时间:2011-09-30 19:51:21

标签: javascript mootools

假设我有一个动态加载页面的页面。当每个页面加载到DOM中时,会添加该页面中元素的事件。

如果用户加载另一个页面,之前加载的元素将从DOM中删除。当然,因为元素本身不再存在,所以映射到这些元素的任何事件都不再起作用。

但是,他们也被删除了吗?或者他们是否坐在用户的记忆中,占用空间?

随访: 是一个定义如下的函数:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

可以使用event = null轻松删除该事件(或者我假设!)...

但是如果事件没有保存到局部变量怎么办?

$('foobar').addEvent('click', function() {
    alert(1);
});

谢谢!

3 个答案:

答案 0 :(得分:1)

有趣的问题......请读一读:https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues

要使用jQuery删除事件侦听器,请参阅http://api.jquery.com/unbind/

答案 1 :(得分:1)

我发现IE的旧版本似乎在添加和删除大量绑定到它们的事件的元素方面存在问题。主要原因是无法进行垃圾回收的循环引用。您可以在此处找到更多信息:http://msdn.microsoft.com/en-us/library/Bb250448

设置为null不会删除事件,它只会删除对事件的引用。您需要同时使用element.removeEventListener和element.detachEvent(取决于浏览器),或者如果您使用的是jquery,unbind应该可以正常工作。

此外,还有一些可用于检测泄漏的工具,这个工作效果很好(根据同事的说法):http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

答案 2 :(得分:1)

首先。什么?这毫无意义:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

它不会像您想象的那样将事件保存到局部变量中。它将foobar element object的引用保存到event变量中 - 大多数mootools元素方法将返回this进行链接,这是元素本身而不是方法的结果(除非它是一个getter喜欢'.getStyle')。

然后取决于你如何摆脱接下来发生的元素。首先,element.destroy,在此处找到:https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L728

它将从dom和内存中删除元素,并以安全的方式清空它。它将依赖于浏览器的GC清理一旦它消失,mootools将不会为你的元素本身做任何壮观的GC,但它确实在子节点上运行特殊的clean函数:{{ 1}}。

clean方法还删除了附加到div的子元素的任何事件处理程序和存储。

THEN。由mootools添加的事件进入元素存储。元素存储位于元素proto使用的闭包后面的对象中。为了测试它,我们将重新实现它并使其可穿透(一个称为存储的全局对象),以便我们可以检查父项消失后引用会发生什么:

http://jsfiddle.net/dimitar/DQ8JU/

var children = clean(this).getElementsByTagName('*');
所有这一切都证明了这一点,mootools清理你需要清理的所有东西。只要你不对你使用的元素使用任何内联(function() { var storage = this.storage = {}; // make it puncturable var get = function(uid){ return (storage[uid] || (storage[uid] = {})); }; Element.implement({ retrieve: function(property, dflt){ var storage = get($uid(this)), prop = storage[property]; if (dflt != null && prop == null) prop = storage[property] = dflt; return prop != null ? prop : null; }, store: function(property, value){ var storage = get($uid(this)); storage[property] = value; return this; }, eliminate: function(property){ var storage = get($uid(this)); delete storage[property]; return this; } }); })(); // read it. var link = document.getElement("a"); var uid = link.uid; // will reference the mootools unique id for it // add an event handler link.addEvent("click", function(e) { console.log("hi"); this.destroy(); // see what's left in storage for that element. console.log(storage[uid]); // storage should be empty. console.log(storage); }); link.getFirst().addEvent("mouseenter", function() { console.log("over"); }); // check to see if it is there via element storage API. console.log(link.retrieve("events").click); // check to see if it's there via our puncture console.log(this.storage[uid]); // see all events in storage, inc child element: console.info(this.storage); 内容,你就会没事的。在mootools的垃圾收集和浏览器之间,你得到了很好的报道。请注意,如果回调是匿名的,您可以在单个元素上堆叠多个事件。