8

假设我已将各种事件侦听器附加到各种表单元素。之后,我想删除整个表单。在删除它们所连接的元素之前,是否需要删除javascript事件侦听器?

是否有必要(或建议)注销表单及其元素上存在的任何事件处理程序?如果是这样,删除元素集合中所有侦听器的最简单方法是什么?不这样做的后果是什么?我使用Prototype,如果它很重要。

这就是我实际做的。我有一个简单的形式,像这样:

<form id="form"> 
    <input type="text" id="foo"/> 
    <input type="text" id="bar"/> 
</form> 

我观察输入各种事件,如:

$('foo').observe('keypress', onFooKeypress); 
$('bar').observe('keypress', onBarKeypress); 

的形式是通过AJAX提交和响应是表格的新副本。我用一个像$('form').replace(newForm)这样的新副本替换旧的表单。我是否积累了一堆事件?

回答

3

是的,有点。不足以成为一个巨大的问题,但在这些情况下IE的老版本会泄漏。

从Prototype 1.6.1(目前在其最终版本候选版本)开始,该库在页面卸载时处理此清理。当你使用Prototype添加一个事件观察者时,它保持对数组中该元素的引用;在页面卸载时,它遍历该数组并删除所有观察者。

但是,如果用户要在此页面上停留一段时间,则内存使用量将在页面的整个生命周期内累积。您有几种选择:

  1. 请收听形式,一个永远不会被取代的祖先事件。然后,在你的处理程序中,检查事件来自哪里。 (即“事件代表团”)

  2. 在致电Element#replace之前,明确注销所有呼叫。在你的榜样,你会怎么做:

    $('foo', 'bar').each(Element.stopObserving); 
    

这等同于调用stopObserving不带参数的,其中有一个给定的元素上删除所有处理的效果。

我建议选择1

(我们已经谈到了原型的未来版本的Element#updateElement#replace部分做自动监听去除,但它是一个性能折衷。)

4

未注册的事件可能无法自动释放其内存。在老版本的IE中,这尤其是个问题。

原型用于拥有自动垃圾收集系统,但该方法在版本1.6中已被删除。它记录在here。我不知道,删除方法是否意味着垃圾收集不再发生,或者方法不再公开可用。另外请注意,它只是在页面卸载时被调用,这意味着如果您的用户在进行大量AJAX和DOM更新的同时长时间呆在同一页面上,即使在一次页面访问期间,内存也可能会泄漏到不可接受的程度。

0

在Jonas下面提到的情况下,从元素中删除任何事件侦听器总是好事。

相关问题