Precise explanation of JavaScript <-> DOM circular reference issue

Posted by Joey Adams on Stack Overflow See other posts from Stack Overflow or by Joey Adams
Published on 2012-04-10T16:25:09Z Indexed on 2012/04/10 17:29 UTC
Read the original article Hit count: 252

One of the touted advantages of jQuery.data versus raw expando properties (arbitrary attributes you can assign to DOM nodes) is that jQuery.data is "safe from circular references and therefore free from memory leaks". An article from Google titled "Optimizing JavaScript code" goes into more detail:

The most common memory leaks for web applications involve circular references between the JavaScript script engine and the browsers' C++ objects' implementing the DOM (e.g. between the JavaScript script engine and Internet Explorer's COM infrastructure, or between the JavaScript engine and Firefox XPCOM infrastructure).

It lists two examples of circular reference patterns:

  • DOM element → event handler → closure scope → DOM

  • DOM element → via expando → intermediary object → DOM element

However, if a reference cycle between a DOM node and a JavaScript object produces a memory leak, doesn't this mean that any non-trivial event handler (e.g. onclick) will produce such a leak? I don't see how it's even possible for an event handler to avoid a reference cycle, because the way I see it:

  • The DOM element references the event handler.

  • The event handler references the DOM (either directly or indirectly). In any case, it's almost impossible to avoid referencing window in any interesting event handler, short of writing a setInterval loop that reads actions from a global queue.

Can someone provide a precise explanation of the JavaScript ↔ DOM circular reference problem? Things I'd like clarified:

  • What browsers are effected? A comment in the jQuery source specifically mentions IE6-7, but the Google article suggests Firefox is also affected.

  • Are expando properties and event handlers somehow different concerning memory leaks? Or are both of these code snippets susceptible to the same kind of memory leak?

    // Create an expando that references to its own element.
    var elem = document.getElementById('foo');
    elem.myself = elem;
    
    // Create an event handler that references its own element.
    var elem = document.getElementById('foo');
    elem.onclick = function() {
        elem.style.display = 'none';
    };
    
  • If a page leaks memory due to a circular reference, does the leak persist until the entire browser application is closed, or is the memory freed when the window/tab is closed?

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about internet-explorer