繁体   English   中英

JavaScript垃圾收集这个吗?

[英]Does JavaScript garbage collect this?

每隔一段时间我就会发现自己在做下面的事情

var img = new Image();
img.src = 'php/getpic.php?z=' + imid + '&th=0';
img.onload = function(){drawImages(img,contexts,sizes)};

说明

  1. 创建HTML图像元素。
  2. 分配其src属性
  3. 分配其onload事件
  4. 将一个或多个Canvas上下文传递给事件处理程序
  5. 将加载的图像绘制到画布上

我不清楚的是这个问题 - JavaScript垃圾收集器是否会处理丢弃img元素的任务,或者我是否需要自己执行此操作,否则将面临一个低内存泄漏?

它将在IE 6和7 (以及非常旧版本的FF)中泄漏 ,因为它在JavaScript和DOM之间创建了循环引用。 IE 6和7不能垃圾收集在两个世界之间具有循环引用的任何对象,因为它们使用单​​独的垃圾收集器。

现代浏览器可以处理这个而不会泄漏。

为防止它在IE 6和7中泄漏,请在完成img执行此操作:

img.onload = null;

如果您只关心现代浏览器,则不必担心它。 (我很高兴IE 6和7的市场份额最终足够低,以表明这一点!)


更新

您为onload分配的函数会创建一个闭包。 该闭包包含对img的引用。 只要该闭包存在于JScript的内存中(JScript是JavaScript的IE实现的名称), img就不能从DOM的内存中进行垃圾收集。 同样,只要img存在于DOM的内存中,闭包就不能从JScript的内存中进行垃圾收集,因为img.onload具有对你的函数的引用。 这是一个循环参考。 换句话说,仅仅因为drawImages执行一次并不意味着它不会再次执行(JScript引擎不知道onload只会触发一次 - 这是DOM的域),所以JScript必须保持闭包活着。

您显示的模式是已知在IE 6和7中创建内存泄漏的经典模式。它包括(1)DOM节点,(2)该DOM节点上创建闭包的事件处理程序,(3) )返回闭包内DOM节点的引用。

如果您担心内存泄漏,我建议您使用Google Chrome堆调试器 在您的情况下,我做了一个简单的测试,可以验证您的特定模式是否会产生内存泄漏。

<html>
    <head>
        <script>
            function test() {
                var img = new Image();
                img.src = 'php/getpic.php?z=1&th=0';
                img.onload = function(){ drawImages(img,contexts,sizes); };
            }
        </script>
    </head>
    <body>
        <input type="button" onclick="test()" value="test" />
    </body>
</html>

我建议你在测试之前按“test”一次,以避免结果中出现不必要的噪音(在第一次代码运行时,内存中会添加一些东西,这并不意味着内存泄漏)。

获取堆快照,按测试并获取堆快照。 如果您想要实际结果,则必须将视图从“摘要”切换为“比较” 如果视图为空(在我测试的情况下),则表示在该步骤期间未添加任何内容,这意味着它没有内存泄漏。 在另一种情况下,它将显示快照之间添加或删除的内容。

注意:此方法无法帮助您解决具有自身问题的旧浏览器的内存泄漏问题,但这是在大多数现代浏览器中找到会导致内存泄漏的问题的一个很好的步骤。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM