by Sundarram P. V.

Saturday, April 11, 2009

OOPS in Javascript: Part III

Apart from using inheritance and prototype for defining an object, there is closure which is strong and often misused feature in javascript. It is one feature I love and knowingly or unknowingly everyone would have used this feature. It is something like whenever a function is defined inside another function, all the variables inside the parent function exists even after the parent function has returned. It is something in the lines of creating a parallel world each time you invoke a function.


/**
* A simple example of closure
*/
var rank = 0;
function greet(name) {
var my_rank = ++rank;
/* adding a anonymous function to greet person after 5 seconds*/
window.setTimeout(function() {
alert("hi " + name + " you came in " + my_rank);
}, 5000);
}

greet("ram");
greet("geetha");


To create a closure, two things are needed,
1. Creation of a function inside a parent function.
2. Send the reference of child function outside the scope of parent function.

Firstly all the variables declared inside a function can be accessed only inside the function, unless explicitly it is passed as a reference outside. In case of closure, all those variables the child function could access will live until its reference is not deleted.
Javascript as you know, doesnt want you to manage memory and uses garbage collection to free memory. All that the garbage collector is looking for is reference count of each instance, and in this particular case my_rank, name and also the anonymous function. It will not release these resources until there is a setTimeout trigger, and it removes the reference of this anonymous function.


class2 = function () {

};

class2.prototype = {
manager : function (params, postcallback) {
var my_dailog;
var usr_callback = function(filename) {
//make ajax call and get the content
my_dailog.hide();
};
//get user input from dailog,
my_dailog = new Dailog({
message : "Enter the name of the file",
callback : usr_callback
});
my_dailog.show();
},
req : function() {
var my_div = document.getElementById('status');
var content_div = document.getElementById('content');

my_div.innerHTML = "working...";

var callback = function(params) {
my_div.innerHTML = "Done.";
content_div.innerHTML = params;
};
this.manager({
url : "http://www.ajaxian.com"
}, callback);
}
};

var ob = new class2();
ob.req();

If for some reason, setTimeout's internal code fails to remove anonymous function's reference or doesnt have a mechanism to release its reference, all these variable will be like a zombie or in technical terms leaked memory. The problem will multiply when this function is called a hundred times, boggling down a lot of memory. This memory will never be claimed back until there is a window.unload. In the above example, all we are doing is try to get the name of the file so that it can be updated. Both manager and the req, functions are using closures, and if not handled properly can and will lead to a memory leak. The leak will only occur when there is a reference to anonymous function present outside of its scope. IE's internal handling of closures is somewhat different when compared with that of Firefox or Safari and also leaks a lot of memory.
Memory leak is not a serious problem for any page which doesnt live for a longer period of time. Detection of leaks are tricky with any language, and its very difficult to debug in complex applications. It is bad for an application like gmail which runs throughout the day. It is a good idea to reload the page over a period of time.

___