Hey there,
The core source of memory leaks in JS is circular references between the
DOM and the JS object space. Essentially this happens when you maintain
refs to DOM nodes from your JS *and* put refs to JS objects from the
same closure in expando properties of these DOM nodes.
I realise this may sound convoluted :-) Here's a straightforward example:
function SuperDuperWidget(nodeForUI) {
if (nodeForUI._superDuper) return;
this.element = nodeForUI; // That's your JS->DOM ref -- "outbound"
// … some more init
nodeForUI._superDuper = this; // That's your DOM->JS ref -- "inbound"
}
This sort of pattern is fairly common, and sometimes MUCH hard to spot
(you could have indirect circular refs, say jsA -> jsB -> node -> jsA),
and this essentially defeats garbage collection on most JS runtimes,
which rely to some degree on reference counting.
The solution I like most is to replace DOM->JS refs by JS-side "maps"
(or hashtables, or dictionaries, or associative arrays: different names
for the same concept). This would look a bit like this (assuming your
nodes all have unique IDs, so as to make proper map keys):
var SuperDuperWidget = (function() {
var nodeToHandlerMap = {};
return function SuperDuperWidget(nodeForUI) {
if (nodeToHandlerMap[nodeForUI.id]) return;
this.element = nodeForUI;
// … some more init
nodeToHandlerMap[nodeForUI.id] = this;
};
})();
The surrounding closure here is there to make sure nodeToHandlerMap is
actually private to SuperDuperWidget. Think of it as a static private
member for the SuperDuperWidget "class."
I'm a big fan of Prototype myself, so when I use this I usually replace
the "nodeForUI.id" in the first check by "$(nodeForUI).identify()" to
make sure the node HAS a unique ID (in case it didn't have any before,
that is).
Best,
--
Christophe Porteneuve aka TDD
[email protected]
_______________________________________________
JSMentors mailing list
[email protected]
http://jsmentors.com/mailman/listinfo/jsmentors_jsmentors.com