Edit: On further examination Firefox does not seem to be doing this, but Chrome definitely does. I guess its just a bug with a new browser - for every event an I/O Read also occurs in Chrome but not in FF.
When I load the following page in a browser (I've tested in Chrome and Firefox 3 under Vista) and move the mouse around the memory always increases and does not ever seems to recede.
Is this:
- expected behaviour from a browser
- a memory leak in the browser or
- a memory leak in the presented code?
.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>test</title>
</head>
<body>
<script>
var createEl = function (i) {
var el = document.createElement("div");
var t = document.createTextNode(i.toString());
el.appendChild(t);
t=null;
el.id=i.toString();
var fn = function (e) {};
el.addEventListener("mouseover", fn, false);
//el.onmouseover = fn;
fn = null;
try{
return el;
}
finally{
el=null;
}
//return (el = [el]).pop();
};
var i,x;
for (i= 0; i < 100; i++){
x = createEl(i)
document.body.appendChild(x);
x = null;
}
</script>
</body>
</html>
The (el = [el].pop())
and the try/finally
ideas are both from here, though they do not either seem to help - understandably since they are only meant to be ie6 fixes.
I have also experimented with using the addEventListener and the onmouseover methods of adding the events. The only way I have found to prevent memory from increasing is to comment out both lines of code.
Well this is not how I'd handle this at all, and I can't replicate the behaviour so all I can tell you is the problem you're having memory wise is likely because of whatever is in the
fn
function, and unless it's a closure you should be definingfn
outside of thecreateEl
function and merely referencing it within, so only a single instance of that exists in memory.You need to handle the event binding better though (this is not xbrowser safe - at this point I hesitate to suggest jQuery), and that whole
(el =[el]).pop()
reeks of voodoo cruft to me, though I'm happy to be corrected if someone can explain exactly what it achieves.fn is a closure even with no code in it. E.g. try debug with Firebug and set the breakpoint inside that function. All variables defined in closure (fn code + variables that hang around = closure) are theoretically accessible(though I don't know how to access them on practice).
Memory leaks related to event handlers are, generally speaking, related to enclosures. In other words, attaching a function to an event handler which points back to its element can prevent browsers from garbage-collecting either. (Thankfully, most newer browsers have "learned the trick" and no longer leak memory in this scenario, but there are a lot of older browsers floating around out there!)
Such an enclosure could look like this:
The fact that
fnOver
andfnOut
reach out to their enclosing scope to referenceel
is what creates an enclosure (two, actually — one for each function) and can cause browsers to leak. Your code doesn't do anything like this, so creates no enclosures, so shouldn't cause a (well-behaved) browser to leak.Just one of the bummer of beta software, I guess. :-)