在删除附加的元素之前,是否需要删除javascript事件侦听器?

时间:2009-07-16 15:52:04

标签: javascript events javascript-events event-handling prototypejs

假设我已将各种事件侦听器附加到各种表单元素。后来,我想删除整个表单。

是否有必要(或建议)取消注册表单及其元素上存在的任何事件处理程序?如果是这样,删除元素集合上所有侦听器的最简单方法是什么?不这样做的后果是什么?如果重要的话,我正在使用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 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

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

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

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

  1. 在表单的祖先上侦听事件,永远不会被替换。然后,在您的处理程序中,检查事件的来源。 (即“事件授权”)

  2. 在致电Element#replace之前,明确取消注册所有来电。在您的示例中,您将执行以下操作:

    $('foo', 'bar').each(Element.stopObserving);
    
  3. 这相当于不带参数调用stopObserving,这样可以删除给定元素上的所有处理程序。

    我建议选项1。

    (我们已经讨论过在Element#updateElement#replace的一部分中将Prototype的未来版本中的自动侦听器删除,但这是性能权衡。)

答案 2 :(得分:0)

如果Jonas在下面提到的场景中,从DOM中删除的元素中删除任何事件侦听器总是好的。