简体   繁体   中英

Am i creating a memory leak?

I have a JavaScript closure which I keep recreating throughout the life time of my web application (single full-ajax page).

I would like to know if it's creating a memory leak.

Here is an example JSFIDDLE

The code in question:

function CreateLinks() {

    var ul = $("<ul></ul>").appendTo('div#links');

    for (var i in myLinks) {

        var li = $('<li>' + myLinks[i].name + '</li>').appendTo(ul);

        //closure starts here
        (function (value) {
            li.click(function (e) {
                $('div#info').append('<label>' + value + '</label><br />');
                RecreateLinks();
            });
        })(myLinks[i].value);

    }
}

You should be okay IF you make sure that you avoid binding multiple click handlers in the RecreateLinks() function; this can be done by explicitly unbinding existing ones, removing the DOM nodes or making sure that you won't be adding multiple click handlers.

Browsers are getting better at memory allocation strategies, but you shouldn't assume too much. If memory usage is a big concern, try to avoid creating too many closures of which you're not sure they will get garbage collected. One such approach is to use .data() to store your value object and then use a generic click handler instead of a closure.

Profiling JavaScript is not so simple; Chrome does have a Profile tool that can monitor CPU and data performance. This can give you a pretty good gauge on the expected memory consumption, but Chrome is not all browsers, keep that in mind.

Depending on how smart the browser is, it may be better to have "myLinks[i].value" an attribute on your <li> rather than passed via closure. Certain dumb browsers have issues collecting garbage when an event handler references a variable from outside it's scope. JavaScript and DOM run two different GC and the JS one doesn't realize the DOM element/eventhandler is gone and that the variable is no longer in use. This issue may be cleared up by properly removing the event handler via javascript rather than just disposing of the element which it is attached to.

Something akin to:

li.attr('lvalue',myLinks[i].value);
...
var value = $(this).attr('lvalue');

This setup would also allow you to use

$('#links > ul > li').live('click',function(){...});

Which would remove the need for adding individual events each time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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