RSS

Closures and IE Circular References

24 Feb

the below nice article is from http://siteexperts.spaces.live.com/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry

Memory Leak Detection Tool

==================================================================================

A little tip for you advanced Javascripters…

First, if you are not familiar with JavaScript closures, I highly recommend you read up on them. They are extremely powerful.  However, they are also very unforgiving in they quickly generate memory leaks.  IE has an issue where it leaks memory when a circular reference is created between a com object and a javascript object.  In IE, the DOM is implemented via com.

So looking at a simple closure (noticed the nested function):

function DoThis()
{
var el = document.createElement(“div”);
el.attachEvent(“onclick”,DoThis);
function DoThis()
{
alert(“clicked”);
}
}

creates a new scope and generates a circular reference that will leak memory in IE. This memory is not reclaimed until the browser closes. The simplest solution is to pretend there is no garbage collector for objects and make sure you always clean-up after yourself.

Fixed version:
function DoThis()
{
var el = document.createElement(“div”);
el.attachEvent(“onclick”,DoThis);
window.attachEvent(“onunload”,Cleanup);
function DoThis()
{
alert(“clicked”);
}
function Cleanup()
{
el.detachEvent(“onclick”,DoThis);
window.detachEvent(“onunload”,Cleanup);
el = null;
}
}

What makes closures interesting?

If you don’t know, I am going to help you figure it out on your own. Let’s take a simple example using the setTimeout method.

Today, it is difficult to pass rich state to a function called on a timer. The setTimeout method takes two arguments, a function to execute, and how long to wait before executing it.  For example:

function twoSeconds()
{
alert(“Two Seconds have past”);
}
setTimeout(twoSeconds,2000);

Now, unfortunately there is no way to send arguments to that function (and before the JavaScript experts jump in, I do not believe serializing the values to a string is an option – most scenarios I deal with require object references)

Today, the typical (and hard to maintain) approach is to store some state in a global:

var objState = {name:”foo”,message:”Hi”};

function twoSeconds()
{
alert(objState.message);
}
setTimeout(twoSeconds,2000);

I hopefully don’t have to explain why that is bad :-).

Now let’s try using closures:

function twoSeconds(arg1,arg2)
{
function Execute()
{
alert(arg2);
}
return Execute;
}

setTimeout(twoSeconds(“foo”,”Hello World”),2000);

Look closely at the above code.  Notice that the function twoSeconds returns a function pointer to the nested Execute function (which creates a new scope chain). After two seconds, the Execute function will be called.  When Execute is called, it has access to the arguments up the entire scope chain (so arg1 and arg2 are accessible).  Each time you call the twoSeconds function, a new and independent scope chain is created.

Below is an alternative approach that performs the setTimeout directly in the twoSeconds function:

function twoSeconds(arg1,arg2)
{
function Execute()
{
alert(arg2);
}
setTimeout(Execute,2000);
}

twoSeconds();

If you step back and look at the bigger picture, you will notice that closures open up the door for encapsulating private functionality and provide a very valuable approach for avoiding the mass creation of global variables.

function myObject()
{
var privateVar=1;
var privateVar=2;
function PrivateMethod()
{
// Do Something;
}
this.publicMethod = function()
{
PrivateMethod();
}
}

var newObj = new myObject();

=================================================================================

Advertisements
 
1 Comment

Posted by on February 24, 2009 in Javascript / DOJO, Web

 

Tags: , , , ,

One response to “Closures and IE Circular References

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: