3

All,

I wonder why this is a memory leak:

window.onload = function outerFunction(){
    var obj = document.getElementById("app")
    obj.onClick = function innerFunction(){
        alert("Hi, I will leak");
    }
}


<button id="app">Click Me</button>

This example above says: a javaScript object(obj) contains a reference to a DOM object(referenced by the id "app"). 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.

And it says the solution is: at the end of function outerFunction, set the obj = null

My confuse is:

Why it says the DOM has reference to that obj? I can not understand this. And why this is a memory leak?

Kuan
  • 11,149
  • 23
  • 93
  • 201
  • 6
    Where did you get this example? – RaminS Jan 31 '19 at 23:05
  • It is a memory leak because since X refers to Y and Y refers to X, then neither X nor Y can be garbage collected. They both have a reference count greater than 0, and are locked. It is a circular reference between the DOM and JS world – jo_va Jan 31 '19 at 23:06
  • This type of *pattern* isn’t a memory leak unless you’re using IE7, but this specific example isn’t a memory leak at all because the button is always there. Can’t get rid of the function if the user can call it any time by clicking. – Ry- Jan 31 '19 at 23:07
  • @Gendarme Sorry, it is from a post long ago, I do not quite remember the URL. – Kuan Jan 31 '19 at 23:09
  • @jo_va Thanks, my confuse is how Y refers to X? – Kuan Jan 31 '19 at 23:10
  • @Ry- Thanks, if we remove that button, will onClick still exist in memory And why(say we are in IE7)? – Kuan Jan 31 '19 at 23:11
  • You have a closure over the DOM via the event attachment. The closure references the obj variable. To fix it, declare the event handler as a standalone function outside of outerFunction, that way you won't have a closure over obj, which refers to the DOM – jo_va Jan 31 '19 at 23:13
  • I think this used to be a problem in IE long time ago, but not in today's browsers. – Felix Kling Jan 31 '19 at 23:14
  • Here is an article: http://www.javascriptkit.com/javatutors/closuresleak/index3.shtml – jo_va Jan 31 '19 at 23:16
  • @jo_va Sorry, I guess I am confused about the concept of leak: I thought after outerFunction gets called, the only space allocated is for innerFunction, why there is a leak? – Kuan Jan 31 '19 at 23:16
  • 1
    Probably related: [Memory leak risk in JavaScript closures](https://stackoverflow.com/questions/11186750/memory-leak-risk-in-javascript-closures) – Felix Kling Jan 31 '19 at 23:17
  • 1
    The leak is that `obj` wouldn't be garbage collected in older browsers, even though it's not referenced anymore. – Felix Kling Jan 31 '19 at 23:17
  • @Kuan, innerFunction still lives after the invocation of outerFunction and innerFunction has a closure which holds the obj variable from being garbage collected, hence the leak – jo_va Jan 31 '19 at 23:17
  • @FelixKling Thanks, but I still not get why it WAS a problem? Could you give a brief explanation from the perspective of memory allocation? – Kuan Jan 31 '19 at 23:18
  • See the other question I linked to. – Felix Kling Jan 31 '19 at 23:18
  • Because it's a [closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). – RaminS Jan 31 '19 at 23:19
  • @jo_va so you are saying since it creates a closure for that click handler function, EVEN nothing is referred inside click handler, that obj variable still can be released? And the memory leak mean the memory space allocated for that obj variable? – Kuan Jan 31 '19 at 23:24
  • 1
    @Kuan, yes I think so, since it is declared inside outerFunction, its closure scope will include obj, even if you don't refer to it. – jo_va Jan 31 '19 at 23:28
  • @FelixKling Ok, get it. So it is nothing about that DOM memory allocation, it is all about that little space allocated for that obj varible. – Kuan Jan 31 '19 at 23:28
  • 1
    I will put that information in an answer, is that correct? – jo_va Jan 31 '19 at 23:34
  • @ jo_va Thanks, could you explain it more from memory allocation perspective? – Kuan Jan 31 '19 at 23:35

1 Answers1

3

The following article is old, and this is not an issue anymore

The issue is described in this article:

window.onload = function() {
    var obj = document.getElementById("element");

    // this creates a closure over "element"
    obj.onclick = function(evt) {
        ... logic ...
    };
};

Here is a diagram describing the closure which creates a circular reference between the DOM world and the JS world.

enter image description here

The above pattern will leak due to closure. Here the closure's global variable obj is referring to the DOM element. In the mean time, the DOM element holds a reference to the entire closure. This generates a circular reference between the DOM and the JS worlds. That is the cause of leakage.

From the MDN web docs: A closure is the combination of a function and the lexical environment within which that function was declared. In that case the lexical environment is the window.onload function, which includes the obj variable.

jo_va
  • 13,504
  • 3
  • 23
  • 47
  • 2
    Worth mentioned that this is not an issue anymore and that the article is likely very old: *"We should keep in mind that, although it is the market leader, IE is not the only browser in the world."* – Felix Kling Jan 31 '19 at 23:42
  • @FelixKling How this is handled nowadays? – Kuan Jan 31 '19 at 23:52
  • 1
    @Kuan: I assume browsers are just better at detected these kind of dependencies and still garbage collect the object. I can't tell you how garbage collection works in detail. – Felix Kling Feb 01 '19 at 00:13