javascriptjqueryeventsgarbage-collection

Event handlers, closures and garbage collection in Javascript


I'm not running into a memory leak in my application yet, but I'm worried about possible problems in the future. I would like to know if doing something like this:

SomeClass.prototype.someMethod= function() {
    var that= this
    this.$div2.click(function() {
        that.someMethod2();
    });
}

And lets say that this.$div2 is appended to another div this.$div1. If I call

this.$div1.remove();

and later loses the reference of my SomeClass instance does the SomeClass instance gets garbage collected? And what about the HTML element this.$div2? this.$div2 would not be inside the DOM because it is appended to this.$div1.

I ask this because the event handler in this.$div2 might keep a reference to the HTML element this.$div2 and also keeps a reference to the instance of SomeClass through the closure because of the variable "that".

So should I care about properly removing all events and HTML elements like this? Or simply removing the "root" element (this.$div1) solves the problem?


Solution

  • this.$div2 is appended to this.$div1. If I call this.$div1.remove(); and later lose the reference of my SomeClass instance does the SomeClass instance gets garbage collected?

    Yes, when all references to it are lost - also those through event handlers , - the instance can get garbage-collected.

    And what about the HTML element this.$div2? this.$div2 would not be inside the DOM because it is appended to this.$div1.

    It does not matter whether it is currently attached to the DOM. If some non-collectible object references $div1, it also could access its child node $div2 and that one's event handlers, so the instance referenced from the handler would not be collectible.

    I ask this because the event handler in this.$div2 might keep a reference to the HTML element this.$div2 and also keeps a reference to the instance of SomeClass through the closure because of the variable "that".

    That's a circular reference and should get handled well by the engines (when none of the objects inside the circle is referenced from outside it can get collected). However, (old?) Internet Explorers fail to do this when a DOM object is involved in the circle.

    For that reason the .remove jQuery method (code) internally calls the (internal) cleanData method which detaches all event listeners.

    So should I care about properly removing all events and HTML elements like this? Or simply removing the "root" element (this.$div1) solves the problem?

    Yes, calling remove on a jQuery wrapper automatically removes all events (from all child elements) and DOM nodes.