Posted almost 7 years ago. Visible to the public. Repeats.

How to create memory leaks in jQuery

jQuery doesn't store information about event listeners and data values with the element itself. This information is instead stored in the global $.cache object. Every time you add an event listener or data value to a jQuery object, $.cache gains another entry.

The only way that a $.cache entry gets deleted is when you call remove() on the element that put it there!

Since cache entries also have a pointer back to the element that spawned them, it is easy to create DOM elements that can never be garbage-collected.

Below are some ways to create memory leaks. jQuery 2.0 and 2.1 do more or less the same thing, though the store is no longer accessible as $.cache, but everything below will still work:

Mixing jQuery with native DOM manipulation is dangerous

When you remove element using the browser's native DOM manipulation methods, the jQuery cache is not cleaned up. This leads to DOM elements that are detached from the DOM, but can never be garbage-collected.

E. g. if you use removeChild() Archive :

var $element = $('<div></div>'); $element.on('click', function() { ... }); $element.appendTo(document.body); var nativeElement = $element.get(0); document.body.removeChild(element);

Now the element will remain detached from the DOM and stay in memory forever, even if the $element and nativeElement variables go out of scope.

The same applies if you remove elements with innerHTML=:

var $element = $('<div></div>'); $element.on('click', function() { ... }); $element.appendTo(document.body); document.body.innerHTML = '';

While setting an element's innerHTML property to a new string is a very performant operation, it fails to clean up $.cache entries of any elements that get removed. Again the element will remain detached from the DOM and stay in memory forever, even if the $element variables go out of scope.

Note that jQuery's html() Archive method explicitely traverses through all removed elements in order to clean up $.cache.


Detached elements cannot be collected if they have data or event handlers

Let's say that you create a DOM element through jQuery, set a data attribute on it, but then don't attach it to the DOM:

$element = $('<div></div>'); $'foo', 'bar');

After the last line in the code sample above, $element can no longer be garbage-collected, even if the $element variable goes out of scope. This is because the pointer in $.cache blocks its memory from being reclaimed. You need to call $element.remove() (or remove a parent element), to remove the entry in $.cache and allow $element to be garbage-collected.

Note that if you do attach $element to the DOM you can make the fair assumption that will either stay there forever, or that someone will probably remove() it in the future.

Why oh why doesn't jQuery store event handlers with the DOM element?

You might wonder why $.cache even exists. After all jQuery could simply attach event handlers to the Javascript object that represents the DOM element.

The reason for $.cache's existence is that old versions of Internet Explorer could not garbage-collect Javascript objects with circular references. For instance, the following object graph could not be reclaimed by old IE's garbage collector if jQuery would attach event handlers to the element:

var $element = $('<div>Close me</div>'); $element.on('click', function() { $element.remove(); });

Since $element would now contain a reference to the click handler and vice versa, both elements can no longer be garbage collected even if the variables go out of scope.

The Javascript engines of modern IE versions no longer have this issue. This is probably why jQuery 2.x broke browser compatibility and only supports IE9+.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Henning Koch
Last edit:
about 3 years ago
by Besprechungs-PC
1.8, 1.9, 1.10, 1.11, 1.12, 1.13, internet, explorer, jQuery.cache
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more