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

Cor*_*son 10 html javascript jquery memory-leaks

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

我试过了:

  • 从body元素中释放事件
  • 从元素中解除事件的绑定
  • 甚至从HTML元素中删除事件属性

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

<input type="text" onchange="validateString(this)"></input>
Run Code Online (Sandbox Code Playgroud)

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


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

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

<input type="text" onchange="validateString(this)"></input>
Run Code Online (Sandbox Code Playgroud)

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

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

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


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

该代码的作用是:

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

    • 有趣的说明.$('input').removeAttr('onchange');实际上会阻止onchange事件在将来被触发,但不会垃圾收集web检查器中可见的eventListener/DOM内容.

此屏幕截图是在更改事件触发3次后.每次使用相同的HTML呈现100个新的DOM节点,并且onchange在替换HTML之前我试图从每个节点解除绑定事件.

在此输入图像描述


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

在此输入图像描述

Wil*_*son 3

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

这种现象并不是内联事件所特有的。我看到了类似的模式,只是重复分配一个大数组,然后覆盖对该大数组的引用,为 GC 留下大量孤立内存。内存会增加一段时间,然后 GC 就会启动并完成其工作。