javascript - 在 img.onload 上留下处理程序是内存泄漏吗?

标签 javascript html memory-leaks

此代码导致浏览器内存泄漏是否正确?

/**
 * @param {Canvas2DRenderingContext} ctx
 * @param {string} url
 */
function loadImageDrawIntoCanvas(ctx, x, y, url) {
  var img = new Image();
  img.onload = function() {
    ctx.drawImage(img, x, y);
  }
  img.src = url;
};

我的理解是,因为 img 是一个 DOM 元素,并且因为我使用 img.onload 将 JavaScript 附加到它,所以浏览器永远不会对其进行垃圾回收。要更正我需要清除 img.onload 中的

/**
 * @param {Canvas2DRenderingContext} ctx
 * @param {string} url
 */
function loadImageDrawIntoCanvas(ctx, x, y, url) {
  var img = new Image();
  img.onload = function() {
    ctx.drawImage(img, x, y);
    img.onload = null;          // detach the javascript from the Image
    img = null;                 // needed also so the closure doesn't keep
                                // a reference to the Image?
  }
  img.src = url;
};

最佳答案

只要浏览器正确实现,就不应该是泄漏。

旧版本的 Internet Explorer(7 及更早版本)的 GC 无法处理 JS 和 DOM 节点之间的循环引用。因此,有很多指南建议在删除 DOM 节点之前清除事件监听器,而 jQuery 会自动执行此操作。 (注意:其他浏览器可能在某些时候有错误的 GC,但旧的 IE 是著名的。)

这里有趣的部分是 GC 需要知道将来是否会再次触发 onload

我刚刚尝试使用类似于您发布的代码将 275 MB 的图像渲染到 Canvas 上,并且 Chrome 没有泄漏。 (相比之下,如果我将图像存储在循环外的数组中,则会保留 275 MB。)Firefox 可能会泄漏 [一些?],但很难说,因为它的内存开销比 Chrome 高得多。

为什么?

  • 在 javascript 端,onloadloadImageDrawIntoCanvas 都已完成执行,并且没有剩余对 img 的引用。
  • 在浏览器实现方面,他们做了一些功能上等同于在您调用 img.src= 时增加对 img 的引用计数,然后减少一次onload 被触发。 Chrome 有两种针对此类泄漏的测试( 12 )。

关于javascript - 在 img.onload 上留下处理程序是内存泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37076977/

相关文章:

javascript - 检查输入并将其转换为适当的类型以防止 XSS

javascript - 线性渐变无法覆盖图像背景

Java Apache-poi,excel 文件的内存泄漏

java - 通过创建一个新数组并确保没有发生内存泄漏来扩展 Java 数组

javascript - <button> 在 HTML 中单击时改变颜色?

javascript - 在 React js 中做一次,然后每 15 秒做一次

javascript - 使用 jquery 和 contenteditable 更新值 ="true"

javascript - Innerhtml 创建文本区域字段

html - 具有后备功能的响应式 <picture> 图片

c++ - 在 Windows-8 64 位中通过 eclipse luna 运行 valgrind/其他内存检查