最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Does JavaScript garbage collect this? - Stack Overflow

programmeradmin10浏览0评论

Every once in a while I find myself doing something along the lines of the following

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

Explanation

  1. Create an HTML image element.
  2. Assign its src attribute
  3. Assign its onload event
  4. Pass one or more Canvas contexts to the event handler
  5. Draw the loaded image to the canvases

The thing I am not clear about is this - will the JavaScript garbage collector deal with the task of discarding the img element or do I need to do it myself or else face a slooow memory leak?

Every once in a while I find myself doing something along the lines of the following

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

Explanation

  1. Create an HTML image element.
  2. Assign its src attribute
  3. Assign its onload event
  4. Pass one or more Canvas contexts to the event handler
  5. Draw the loaded image to the canvases

The thing I am not clear about is this - will the JavaScript garbage collector deal with the task of discarding the img element or do I need to do it myself or else face a slooow memory leak?

Share Improve this question edited Jan 22, 2014 at 15:51 Kara 6,22616 gold badges53 silver badges58 bronze badges asked Nov 20, 2012 at 15:30 DroidOSDroidOS 8,94018 gold badges114 silver badges189 bronze badges 2
  • 5 Aside: Swap steps 2 and 3. If the image is cached, IE will fire onload before the assignment onload = function() {} executes. – user1233508 Commented Nov 20, 2012 at 15:34
  • DrawImages should not be too relevant here - it simply draws the image that has been loaded on to one or more canvases (passed as contexts in the last line) that are in the DOM. Once that is done the img object has no further use. The images are never cached in this instance. – DroidOS Commented Nov 21, 2012 at 4:50
Add a ment  | 

2 Answers 2

Reset to default 7

It will leak in IE 6 and 7 (and very old versions of FF) because it creates a circular reference between JavaScript and the DOM. IE 6 and 7 can't garbage collect any objects which have circular references between the two worlds because they use separate garbage collectors.

Modern browsers can handle this without leaking.

To prevent it from leaking in IE 6 and 7, do this when you're done with img:

img.onload = null;

If you only care about modern browsers, you don't have to worry about it. (I'm so glad IE 6 and 7 are finally low enough in market share to suggest that!)


Update

The function you assign to onload creates a closure. That closure contains a reference to img. img can't be garbage collected from the DOM's memory as long as that closure exists in JScript's memory (JScript is name for the IE implementation of JavaScript). Likewise, the closure can't be garbage collected from JScript's memory as long as img exists in the DOM's memory, because img.onload has a reference to your function. This is a circular reference. In other words, just because drawImages executes once doesn't mean it won't execute again (the JScript engine doesn't know onload only fires once -- that's the DOM's domain), so JScript has to keep the closure alive.

The pattern you have shown is the classic pattern that is known to create memory leaks in IE 6 & 7. It consists of (1) A DOM node, (2) An event handler on that DOM node which creates a closure, and (3) A reference back to that DOM node inside the closure.

If you are worried about memory leak what I suggest you is to use the Heap Debugger of Google Chrome. In your case I have made a simple test that can verify if your particular pattern will create a memory leak.

<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>

I remend you to press "test" once before the test to avoid unnecessary noise in the result (there are thing which get added in the memory the first time the code runs and this doesn't mean there's memory leak).

Take a heap snapshot, press test and take a heap snapshot. If you want the actual result you have to switch the view from "Summary" to "Comparaison". If the view is empty (in your case when I tested), it means nothing was added during the step, which mean that it doesn't have memory leak. In the other case, it will show you what was added or deleted between the snapshot.

Note : This method won't help you with memory leak for older browser that have their own issue, but it's a good step to find thing that will cause memory leak in most modern browser.

发布评论

评论列表(0)

  1. 暂无评论