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

时间:2016-05-06 16:11:24

标签: 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附加到它上面,浏览器永远不会垃圾收集它。要纠正我需要清除{/ 1}},如

img.onload

1 个答案:

答案 0 :(得分:3)

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

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

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

我刚尝试使用与您发布的代码类似的代码将275 MB的图像渲染到画布,而且Chrome不会泄漏。 (相比之下,如果我将图像存储在循环外的数组中,则会保留275 MB。)Firefox可能会泄漏[某些?],但很难分辨,因为它的内存开销远远高于Chrome。

为什么?

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