JavaScript: Preventing Memory Leaks

In my last article, I presented the common patterns that lead to Memory Leak in a typical JavaScript Application. This article continues the concept of Memory Leaks and unrolls the prevention techniques for each pattern.

Preventing memory leak patterns:

Prevention is always better than cure. Let’s quickly enlist the prevention techniques for each pattern.

    1. Avoid Global variables: To avoid global variables, make sure the variable is not accessible directly in console window. Write ‘use strict’ in code to let JavaScript engine execute the scripts in Strict Mode. In this mode the runtime will throw errors if you try to create a global variable unintentionally.


‘use strict’;//this will ensure throwing error on unintentional globals
function test() {
global1 = "global variable, will throw error";
this.global2 = "another global variable, will throw error";
}
test(); //function call

    1. Clear Timer function properly: A timer function should never be used anonymously. The best practise says, grab the timer function in a handle and the clear the timer function using the handle to ensure proper closing of timer events.

var slideContent = "This is a very long string perhaps 5000 characters long.";
var stopInterval=false;
var myInterval=setInterval(function() {//myInterval is a handle here
var slider = document.getElementById('slider');
slider.innerHTML = slideContent;
if(stopInterval)
clearInterval(myInterval);//this will clear the interval properly
}, 3000);
//down the line lets say we want to stop the slider timer
stopInterval=true;

    1. Circular DOM references: Minimize the circular DOM references by segregating the responsibility of your code into different components. Any kind of styling should be handled by CSS files rather than in JavaScript. Attached event handlers on DOM should be properly removed before detaching/deleting DOM node.


var slideContent = "This is a very long string perhaps 5000 characters long.";
var slider = document.getElementById('slider');
var startButton=document.getElementById(‘startButton’);
var onClickHandler= function(){
slider.innerHTML = slideContent;
};
startButton.addEventListener(‘click’,onClickHandler);
startButton.removeEventListener(‘click’, onClickHandler);//remove event handlers first
document.body.removeChild(startButton);

  1. Closures: Closures are very important yet complex piece in JavaScript. Since Closures have a bigger scope (up to parent level) it is advised to choose same parent scope information to be used inside closures. This choice is crucial as it decides what all to include in memory until the closure is out of reference.


function outerFunction(){
var bigData = "This is a very long string perhaps 5000 characters long.";
this.innterFunction = function(innerData){
//instead of using the big parent scope object here directly, try to get it as parameter
};
}
//instantiate outerFunction
var oFunction=new outerFunction();
var myData=”Data to be used for clouser”;
oFunction.innerFunction(myData);

What Next?

These are the major prevention techniques for the common Memory Leak patterns. It is important but hard to write a superior code, less prone to memory leak. Memory leak can also be triggered by poor quality browser extensions and addons, in such cases it is important to identify which plugin is causing the issue. As mentioned earlier, Google Chrome provides a variety of tools to monitor the application for memory patterns. You can deep dive into code profiling and observe the leak triggers as well.In my last article, I presented the common patterns that lead to Memory Leak in a typical JavaScript Application. This article continues the concept of Memory Leaks and unrolls the prevention techniques for each pattern.

Preventing memory leak patterns:

Prevention is always better than cure. Let’s quickly enlist the prevention techniques for each pattern.

    1. Avoid Global variables: To avoid global variables, make sure the variable is not accessible directly in console window. Write ‘use strict’ in code to let JavaScript engine execute the scripts in Strict Mode. In this mode the runtime will throw errors if you try to create a global variable unintentionally.


‘use strict’;//this will ensure throwing error on unintentional globals
function test() {
global1 = "global variable, will throw error";
this.global2 = "another global variable, will throw error";
}
test(); //function call

    1. Clear Timer function properly: A timer function should never be used anonymously. The best practise says, grab the timer function in a handle and the clear the timer function using the handle to ensure proper closing of timer events.

var slideContent = "This is a very long string perhaps 5000 characters long.";
var stopInterval=false;
var myInterval=setInterval(function() {//myInterval is a handle here
var slider = document.getElementById('slider');
slider.innerHTML = slideContent;
if(stopInterval)
clearInterval(myInterval);//this will clear the interval properly
}, 3000);
//down the line lets say we want to stop the slider timer
stopInterval=true;

    1. Circular DOM references: Minimize the circular DOM references by segregating the responsibility of your code into different components. Any kind of styling should be handled by CSS files rather than in JavaScript. Attached event handlers on DOM should be properly removed before detaching/deleting DOM node.


var slideContent = "This is a very long string perhaps 5000 characters long.";
var slider = document.getElementById('slider');
var startButton=document.getElementById(‘startButton’);
var onClickHandler= function(){
slider.innerHTML = slideContent;
};
startButton.addEventListener(‘click’,onClickHandler);
startButton.removeEventListener(‘click’, onClickHandler);//remove event handlers first
document.body.removeChild(startButton);

  1. Closures: Closures are very important yet complex piece in JavaScript. Since Closures have a bigger scope (up to parent level) it is advised to choose same parent scope information to be used inside closures. This choice is crucial as it decides what all to include in memory until the closure is out of reference.


function outerFunction(){
var bigData = "This is a very long string perhaps 5000 characters long.";
this.innterFunction = function(innerData){
//instead of using the big parent scope object here directly, try to get it as parameter
};
}
//instantiate outerFunction
var oFunction=new outerFunction();
var myData=”Data to be used for clouser”;
oFunction.innerFunction(myData);

What Next?

These are the major prevention techniques for the common Memory Leak patterns. It is important but hard to write a superior code, less prone to memory leak. Memory leak can also be triggered by poor quality browser extensions and addons, in such cases it is important to identify which plugin is causing the issue. As mentioned earlier, Google Chrome provides a variety of tools to monitor the application for memory patterns. You can deep dive into code profiling and observe the leak triggers as well.[:]