0

All:

I am pretty new to Javascript memory management, currently reading:

https://www.ibm.com/developerworks/library/wa-memleak/wa-memleak-pdf.pdf

Inside this article, for Listing5, the explaination says:

In Listing 5 you see a closure in which a JavaScript object (obj) contains a reference to a DOM object (referenced by the id "element"). The DOM element, in turn, has a reference to the JavaScript obj. The resulting circular reference between the JavaScript object and the DOM object causes a memory leak.

could anyone give me some more detail about how this pattern gets circular reference built up and cause memory leak(a graph will be greatly appreciated)? Especially this part:

The DOM element, in turn, has a reference to the JavaScript obj.

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
};
<button id="element">Click Me</button>
Kuan
  • 11,149
  • 23
  • 93
  • 201
  • Modern Javascript implementations don't suck quite as much as when that document was written. I don't think this pattern is an issue any more. – user2357112 Apr 19 '18 at 23:35
  • @user2357112 Thanks, so for the code alone, I am kinda wondering what part expects GC collect back(since if it can cause leak, it must have something expected to be collected)? – Kuan Apr 19 '18 at 23:47

1 Answers1

1

There is a problem only if you're planning on removing the button element at some point.

The circular reference happens because of the closure caused by outerFunction: innerFunction which is the click event listener of the button will have a reference to obj which is the button. Thus removing the button won't take effect, because a reference to it will always exists (inside its own click event listener), thwarting the garbage collector.

Removing an object in JS happens by the garbage collector when the object no longer have any references to it. Removing the button from the DOM by doing, for example:

document.getElementById("element").remove();

will remove the references to that button from the DOM, but the garbage collector will fail to remove it because there will be another reference to that button inside innerFunction which is to obj (which holds a reference to the button).

The circular reference here is that in order to remove/destroy innerFunction, the button must be destroyed first, and in order to remove/destroy the button, all references to it must be removed including the one inside innerFunction.

Note: In recent browsers you shouldn't worry about those event listeners causing memory leaks.

ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • Thanks, so you are saying for the code above alone, there is no problem? I am wondering why it comments:"// This is used to make the leak significant". – Kuan Apr 19 '18 at 23:34
  • Also, I am kinda wondering, for GC, what memory in this example is expected to collect? – Kuan Apr 19 '18 at 23:37
  • @Kuan **1.** _This is used to make the leak significant_ means that we are attaching further data to our button object, thus when it get memory-leaked, that whole button object (with that additional enormous data) will stay in the memory although we think it is removed. – ibrahim mahrir Apr 19 '18 at 23:42
  • @Kuan **2.** CG is expected to collect the button object including all data associated with/attached to that object like `bigString` and `innerFunction` (onclick). – ibrahim mahrir Apr 19 '18 at 23:44