Closing The Book On Javascript Closures

Filed: Wed, Jun 13 2007 under Programming|| Tags: closures javascript oop

The time has come to address one of Javascript's more powerful features: closures. Simply put, a closure is a variable, created inside a function, which continues to exist after the function has finished executing.

Understanding closures will allow you to avoid damaging memory leaks in Internet Explorer and also allow you to fully exploit private variables and methods when creating Javascript objects.

Hello Closure!

Here's an example which will vividly illustrate the concept.

try {
   alert(closureDemo);
}
catch(err) {
   alert("closureDemo doesn't exist yet, hit 'OK', we'll call the function that creates it and try again"); 
}

var theDemo = function () {
   closureDemo = "This is a closure! This string is displayed in an alertBox outside of the function which created it.";
}

theDemo();
alert(closureDemo);

If you follow along with the code you'll see we try to do an alert with a variable which hasn't been defined yet. We wrapped this in try/catch statements so the error we know will happen won't generate a real error message. Of course, closureDemo doesn't exist yet so the catch block is executed. Next we define a function which will declare closureDemo, then we call the function itself: theDemo(). Finally we issue an alert with closureDemo as the string, and it works!.

The last alert works because we created a closure in the theDemo function. We did it because Javascript has a little quirk where if you don't declare a variable with the var keyword then the variable becomes global, regardless of where it was declared. So at one point in time you've probably created a closure without even realizing it simply because it's easy to forget adding a var keyword before each and every variable in your scripts.

Go ahead and try executing the example with this convenient handy, dandy button:

Child Functions & Closures

So you're probably scratching your head and saying "So what?".

Well there's actually a lot of good reasons to know how and why Javascript creates closures, if only because Internet Explorer tends to leak memory when they're used. A side effect of this is that there's an admonition to never use child functions because they create closures! Which CAN be true, but also can be false -- it all depends on how you write your code. Lets take a look at a child function/closure.

theParent = function () {

   theChild() = function() {
     alert("I'm the baby!);
   }
   
}

theParent();
theChild();

Now any classically trained programmer will look at this code and say "theChild()" can only be called within "theParent()". But in Javascript that is not the case as you can see by clicking this button which will directly call "theChild()" without going through theParent().

The answer as to why this is happening of course is that we are declaring the functions like variables and we are leaving off the var keyword, so theChild becomes global and a closure.

This same example without creating the closure would like like this…

var theParent = function () {

   var theChild() = function() {
     alert("I'm the baby!);
   }
   
}

theParent();
theChild();

In this example, theChild() call at the end of the script will generate an error because to access the function theChild() the call must actually be made within theParent().

More than global variables

A closure is more than a global variable. Take a look at the following object which has become popular at the advanced end of Javascript coding.


var myObject = function() {

   var privateVar = 'This variable is private!';
   
   var privateFunction = function() {
      alert('this function is Private!');
   }
   
   return {
   
      showPrivateVar : function () {
         alert(privateVar);
      },
      
      changePrivateVar : function(val) {
         privateVar = val;
      },
      
      callPrivateFunc : function() {
         privateFunction();
      }
      
   }
}();

The key to understanding what is happening here is to look at the first line and then the last, ignoring everything in between.

var myObject = function() {} ();

You can see we're creating a variable called myObject and that it's a function that won't be receiving any arguments. The braces {} denote where the code will go and it's terminated with another set of parenthesis (), these trailing parenthesis tell javascript to execute the function immediately as it's parsed. What this means is that myObject isn't going to be equal to the function you see, but rather WHAT THAT FUNCTION RETURNS.

So javascript creates the function, executes it, and places the return contents in myObject. The return contents in this case is a javascript object containing 3 methods, showPrivateVar, changePrivateVar, and callPrivateFunc.

What's cool and closurey about all of this is that privateVar and privateFunction can ONLY be accessed by those methods that were returned. The function that creates them doesn't exist now, only the results of the functions exist and those functions have access to privateVar and privateFunction because they are closures, they exist but can be accessed in a very limited way.

Now when we call myObject.showPriavteVar() we'll get an alert box that pops up and says "This variable is private!". Likewise when we call myObject.privateVar('new value'), we can change the value of privateVar and that's the only way privateVar can be changed! And finally we call the private function through the myObject.callPrivateFunc().

So closures are a bit more useful than accidentally creating global variables (potentially interfering with other variables of the same name), and causing inadvertent memory leaks in Internet Explorer. As you start to move from beginning and intermediate javascript to full object-oriented applications, closures can help you protect critical variables and methods both from your own code and other modules and libraries you elect to use.

Working with and around closures

So the first rule of Javascript closures is to always use the var keyword inside your functions unless you are deliberately setting out to create a closure, this even extends to functions you declare with the variable declaration style syntax.

The second rule is to use closures whenever you need to hide variables and methods of an object. This is a fairly advance technique but one which is easily mastered and ultimately very useful in creating true object-oriented applications.