The circular reference problem happens in some browsers when you put a reference to a DOM object on a DOM object as a property on that DOM object. Then, you have two DOM objects pointing at each other. Removing a DOM object with a custom property on it doesn't clear that custom property. A garbage collector that isn't that smart doesn't realize that this DOM reference doesn't count so it gets stuck and there are several ways that this can lead to leaks.
.data() solves this problem because the
The one confusing part of this is that when you read with
.data("key") and the
.data() data structure, then and only then, jQuery will look for an attribute on the DOM object called
"data-key". But whenever you write with
.data() never writes the data to the DOM object, there can't be any of these types of circular references that some browsers have trouble with.
There are some other useful things to know about the
.data() data structure. When you use jQuery's
.remove() to remove elements from the DOM or when you call
$(elem).html("new html"), jQuery clears the
.data(), then you should always remove items from the DOM using jQuery functions so
.data() is cleaned up appropriately. Otherwise, you can get memory leaks this way (both the
.data() data can leak and any removed DOM objects that are referenced in the
.data() can leak. But, if you only use jQuery methods for removing items from the DOM (including the replacing of innerHTML), then jQuery will clean things up appropriately and there will be no leaks.
So, for example, this will create a memory leak:
.data() value you previously stored is now orphaned in jQuery's storage and is essentially a "leak" as it will likely never be cleared. On the other hand, if you do this:
$(elem).data("someKey", "someValue"); $(elem).remove();
Then, jQuery will see that you're removing the DOM element and will also clear the data you stored with
A fairly simple way to see how it works is to create a couple line script with a non-minimized version of jQuery and then just step through a call to
$(elem).data("key", "whatever") in the debugger and watch how it works.