I was reading this article ( http://www.ibm.com/developerworks/web/library/wa-memleak/ ) on IBM’s website about memory leaks in JavaScript when I came across a memory leak that didn’t quite look liked it leaked:
<html>
<body>
<script type="text/javascript">
document.write("Program to illustrate memory leak via closure");
window.onload=function outerFunction(){
var obj = document.getElementById("element");
obj.onclick=function innerFunction(){
alert("Hi! I will leak");
};
obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
// This is used to make the leak significant
};
</script>
<button id="element">Click Me</button>
</body>
</html>
I understood all the other leaks but this one stood out. It says there’s a circular reference between the DOM and JavaScript object but I don’t see it.
Can anyone shed some light on this?
EDIT: The link seems to have been taken down (I even refreshed the page I had up and it was down). Here’s Google’s cache (for as long as that lasts: http://webcache.googleusercontent.com/search?q=cache:kLR-FJUeKv0J:www.ibm.com/developerworks/web/library/wa-memleak/+memory+management+in+javascript&cd=1&hl=en&ct=clnk&gl=us&client=firefox-a )
The assignment to
onclickof theinnerFunctioncreates a function closure that preserves the value of the variables that are in scope ofinnerFunction. This allows the code ininnerFunctionto reference variables above it and is a desirable feature of javascript (something some other languages don’t have).Those variables that are in scope of
innerFunctionincludeobj. So, as long as there is a reference to this closure, the variables in that closure are preserved. It’s a one-time piece of memory usage so it doesn’t accumulate over time and thus isn’t usually significant. But, if you put big data into one of those variables, then and expected it to be freed, then “yes” you would be using more browser memory than you expected.Where this can cause problems is in this particular example, you have a circular reference between JS <==> DOM. In JS, you have preserved (in the function closure) a reference to the DOM object in the
objvariable. In the DOM object, you have preserved a reference to the JS code and the function closure with the assignment to the onclick attribute. Some older browsers are dumb enough that even if you remove the “element” object from the DOM, the circular reference will keep the garbage collector from ever freeing the memory. This is not a problem in modern browsers as they are smart enough to see this circular reference and still free the object if there are no outside references to it.In your particular code, you haven’t actually created a leak because the element is still in the DOM. bigString is just a big chunk of data you’ve attached to the DOM element and it will stay there until you remove that attribute or remove the DOM object. That’s not a leak, that’s just storage.
The only way this would become a leak in IE6 is if you did this:
Now, you’ve removed the object from the DOM (sometime later in your code) and probably expected all memory associated with it to be freed, but the circular reference keeps that from happening in IE6. You could work-around that by doing the following:
or, if you don’t need the
objreference in the closure, you could null the reference from the closure entirely with this:In practice, this is only a meaningful issue in a few cases when the memory usage of a leak could be significant.