解除内存中HTML元素的内联javascript事件

时间:2013-02-09 04:12:10

标签: javascript jquery html memory-leaks

如何从HTML元素中完全取消绑定内联javascript事件?

我试过了:

  • 从body元素中删除事件
  • 从元素中取消绑定事件
  • 甚至从HTML元素中删除事件属性

令我惊讶的是,只有删除onchange属性(.removeAttr('onchange'))才能阻止事件再次触发。

<input type="text" onchange="validateString(this)"></input>

我知道这对代表来说是可能的,这可能是最好的方式,但只是在这里玩。这个例子纯粹是假设,只是为了提出问题。


所以假设的情况就是这样:

我正在编写一个javascript验证库,它通过内联HTML属性将javascript事件绑定到输入字段,如下所示:

<input type="text" onchange="validateString(this)"></input>

但是,我想通过解除我的事件绑定来使图书馆更好一些,这样在单页面应用程序中使用这个库的人不必管理我的事件处理程序,因此它们不会必须通过将输入事件连接到我假设的验证库中的函数来混乱他们的代码......无论如何。这些都不是真的,但它似乎是一个不错的用例。

这是假设验证库的“示例”代码.js:

http://jsfiddle.net/CoryDanielson/jwTTf/


要进行测试,只需键入文本框,然后单击其他位置以触发更改事件。在Web时间轴选项卡上打开并记录Web检查器时执行此操作。突出显示时间轴的区域,该区域与您何时触发更改事件(多次触发更改事件)相关,并且您将在每个更改事件中看到事件侦听器(在下面的窗口中)增加100。如果管理和正确删除后,每个事件侦听器都会在呈现新输入之前被正确删除,但我还没有找到一种方法来正确执行内联javascript事件。

该代码的作用是:

  1. onChange,输入元素触发验证功能
  2. 该功能验证输入并在成功时为边框着色
  3. 然后在1秒后(为了演示内存泄漏)输入元素连续100次替换相同的HTML而不解除更改事件的绑定(因为我不知道如何做到这一点......那就是这里的问题)。这模拟了在单页应用程序中更改视图。这将在DOM中创建100个新的eventListener,通过Web检查器可以看到它。

    • 有趣的说明。 $('input').removeAttr('onchange');实际上会阻止onchange事件在将来被触发,但不会垃圾收集web检查器中可见的eventListener / DOM内容。
  4. 此屏幕截图是在更改事件触发3次后。每次都会使用相同的HTML呈现100个新DOM节点,并且在替换HTML之前,我试图从每个节点取消绑定onchange事件。

    enter image description here


    更新:我回到了这个问题,只是使用JSFiddle做了一个快速的小测试,以确保答案是有效的。我进行了几十次“测试”,然后等待 - 确定,GC已经完成并负责业务。

    enter image description here

2 个答案:

答案 0 :(得分:3)

我认为你没有什么可担心的。虽然无法再引用内存并最终将其进行垃圾回收,但它仍会显示在Web Inspector内存窗口中。当GC决定垃圾收集时(例如,当浏览器内存不足或在一段固定时间之后),内存将被垃圾收集。详细信息由GC实施者决定。您只需单击Web Insepctor窗口底部的“收集垃圾”按钮即可验证这一点。我正在运行Chrome 23,在验证框中输入文本大约5或6次后,内存使用率会崩溃,显然是由于垃圾回收。

这种现象并非特定于内联事件。我只是通过重复分配一个大型数组,然后覆盖对该大型数组的引用,为GC留下了大量的孤立内存,我看到了类似的模式。记忆加速了一段时间,然后GC启动并完成其工作。

答案 1 :(得分:0)

我的第一次尝试是使用off('change'),但似乎你已经尝试过了。它可能不起作用的原因是因为处理程序没有附加.on('change')。我不太了解jQuery如何在内部处理这样的侦听器,但尝试使用.on('change', function ()....bind('change', function ()...附加。