Skip to main content
added 4 characters in body
Source Link
jfriend00
  • 711k
  • 104
  • 1.1k
  • 1k

The assignment to onclick of the innerFunctioninnerFunction creates a function closure that preserves the value of the variables that are in scope of the innerFunctioninnerFunction. This allows the code in innerFunctioninnerFunction to 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 innerFunctioninnerFunction include obj. 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.

The assignment to onclick of the innerFunction creates a function closure that preserves the value of the variables that are in scope of the innerFunction. This allows the code in innerFunction to 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 innerFunction include obj. 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.

The assignment to onclick of the innerFunction creates a function closure that preserves the value of the variables that are in scope of innerFunction. This allows the code in innerFunction to 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 innerFunction include obj. 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.

added 569 characters in body
Source Link
jfriend00
  • 711k
  • 104
  • 1.1k
  • 1k
<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 }; // called later in your code function freeObject() { var obj = document.getElementById("element"); obj.parentNode.removeChild(obj); // remove object from DOM };   </script> <button id="element">Click Me</button> </body> </html> 

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:

<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 }; // called later in your code function freeObject() { var obj = document.getElementById("element"); obj.onclick=null; // clear handler and closure reference obj.parentNode.removeChild(obj); // remove object from DOM } </script> <button id="element">Click Me</button> </body> </html> 

or, if you don't need the obj reference in the closure, you could null the reference from the closure entirely with this:

<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 obj = null; // kills the circular reference, obj will be null if you access if from innerFunction() }; </script> <button id="element">Click Me</button> </body> </html> 
<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 obj.parentNode.removeChild(obj); // remove object from DOM }; </script> <button id="element">Click Me</button> </body> </html> 

Now, you've removed the object from the DOM 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:

<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 obj.onclick=null; // clear handler and closure reference obj.parentNode.removeChild(obj); // remove object from DOM }; </script> <button id="element">Click Me</button> </body> </html> 
<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 }; // called later in your code function freeObject() { var obj = document.getElementById("element"); obj.parentNode.removeChild(obj); // remove object from DOM }   </script> <button id="element">Click Me</button> </body> </html> 

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:

<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 }; // called later in your code function freeObject() { var obj = document.getElementById("element"); obj.onclick=null; // clear handler and closure reference obj.parentNode.removeChild(obj); // remove object from DOM } </script> <button id="element">Click Me</button> </body> </html> 

or, if you don't need the obj reference in the closure, you could null the reference from the closure entirely with this:

<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 obj = null; // kills the circular reference, obj will be null if you access if from innerFunction() }; </script> <button id="element">Click Me</button> </body> </html> 
added 569 characters in body
Source Link
jfriend00
  • 711k
  • 104
  • 1.1k
  • 1k

In practice, this is only a meaningful issue in a few cases when the memory usage of a leak could be significant.

  1. If you have large chunks of data that you store as DOM attributes, then a single object leak could leak a large amount of data. That's usually solved by not storing large chunks of data on DOM objects. Store them in JS where you control the lifetime explicitly.
  2. If you have a long lived page with lots of javascript interaction and an operation that creates/destroys DOM objects can be done many, many times. For example, a slideshow that runs unattended may be creating/destroying DOM objects over and over and over again. Even small amounts of memory leakage per item could eventually add up and cause a problem. In a slideshow I wrote, I just made sure that I didn't put any custom attributes on these particular DOM objects that I was add/removing and that all event handlers were removed before removing the object from the DOM. This should assure that there could be no circular references to them.
  3. Any kind of DOM operation you're doing over and over in a big loop.

In practice, this is only a meaningful issue in a few cases when the memory usage of a leak could be significant.

  1. If you have large chunks of data that you store as DOM attributes, then a single object leak could leak a large amount of data. That's usually solved by not storing large chunks of data on DOM objects. Store them in JS where you control the lifetime explicitly.
  2. If you have a long lived page with lots of javascript interaction and an operation that creates/destroys DOM objects can be done many, many times. For example, a slideshow that runs unattended may be creating/destroying DOM objects over and over and over again. Even small amounts of memory leakage per item could eventually add up and cause a problem. In a slideshow I wrote, I just made sure that I didn't put any custom attributes on these particular DOM objects that I was add/removing and that all event handlers were removed before removing the object from the DOM. This should assure that there could be no circular references to them.
  3. Any kind of DOM operation you're doing over and over in a big loop.
added 569 characters in body
Source Link
jfriend00
  • 711k
  • 104
  • 1.1k
  • 1k
Loading
added 569 characters in body
Source Link
jfriend00
  • 711k
  • 104
  • 1.1k
  • 1k
Loading
Source Link
jfriend00
  • 711k
  • 104
  • 1.1k
  • 1k
Loading