Search code examples
javascriptactionscript-3garbage-collectiondom-events

Javascript, events, event listeners and memory leaks


Having developed various non-trivial applications in Actionscript (which, as a dialect of ECMAScript shares a lot with JS) I'm now used to paying extra attention to (obsessing over) event listeners. At some point, after profiling various apps and reading related literature, it became obvious that the Flash player's garbage collector would have a hard time releasing unused resources when event listeners were present (i.e. added but never removed).

This led to a standard practice of defining (and systematically calling) destructor-like methods for all types that acted as event listeners. The latter were responsible for removing all listeners that were added at initialization-time. As a side effect, this required forgoing the use of unnamed functions as event listeners as all addEventListener(someMethod) calls had to be matched by a 'symmetrical' removeEventListener(someMethod). Another alternative would be using weak references.

Now, moving on to Javascript, judging from how integral unnamed functions (and closures) are to the language, their widespread use as event listeners, as well as the general lack of listener-related cleanup code to be found on the internet, it seems that the aforementioned shortcomings of Actionscript's runtime are not shared by the browser.

Specifically, in the case of plain Javascript and DOM events, I have come to understand that when some part of the document is destroyed, the GC will release all related resources regardless of whether any listeners are attached (something that is not true for AS and its 'document', the display-list).

I suppose that the same holds for jQuery which primarily deals with the DOM (factoring in the possibility that jQuery internally performs its own cleanup in some cases).

Is this correct?

And what about dealing with custom events (and their listeners) which don't originate from the document but are defined and triggered using some library, such as Backbone's Event module or the Node.js EventEmitter? Should one expect a similar cleanup functionality 'for free' or is this clearly a different case where one should take care to remove any added event listeners (from 'dead' objects) in order to avoid memory leaks?

(If this feels too generic, I'd be happy to provide concrete examples as a basis for further discussion)


Solution

  • I don't think there's anything "for free" in Javascript, and I believe it has the same issues with GC on removed DOM elements.

    This is one of the benefits of using a good library. You mentioned jQuery -- it's pretty diligent about removing listeners when altering the DOM. For instance: http://api.jquery.com/remove/

    In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed.

    So don't get too happy, but using something diligently like jQuery can keep you relatively safe.