Introducing the closure
Here is another piece of code. Instead of appending the script inline, we attach it externally:
[Exhibit 4 - Leak test with a closure] <html> <head> <script type="text/javascript"> function LeakMemory(){ var parentDiv = document.createElement("div"); parentDiv.onclick=function(){ foo(); }; parentDiv.bigString = new Array(1000).join(new Array(2000).join("XXXXX")); } </script> </head> <body> <input type="button" value="Memory Leaking Insert" onclick="LeakMemory()" /> </body> </html>
If you don't know what a closure is, there are very good references on the web where you may find it. Closures are very useful patterns; you should learn them and keep them in your knowledge base.
And here is the graph that shows the memory leak. This is somewhat
different from the former examples. The anonymous function assigned to
parentDiv.onclick
is a closure that closes over parentDiv
,
which creates a circular reference between the JS world and DOM and creates
a well-known memory leakage issue:
To generate leak in the above scenario, we should click the button, refresh the page, click the button again, refresh the page and so on.
Clicking the button without a subsequent refresh will generate the leak
only once. Because, at each click, the onclick
event of
parentDiv
is reassigned and the circular reference over the former
closure is broken. Hence at each page load there is only one closure that
cannot be garbage collected due to circular reference. The rest is
successfully cleaned up.
- JavaScript and memory leaks
- Introducing the closure
- More leakage patterns
- Conclusion