Monday, June 18, 2012

JavaScript Closure : “A state of being closed”

This is another fun and interesting aspect in JavaScript programming. Closures are powerful because they enable inner functions to retain access to an outer function's variables even after the outer function has returned. Let’s try to understand it in a fun way.

JavaScript Closure: Analogy

A King has lots of GOLD which he has kept in a secret treasure. There is a map which leads to treasure but its only King who knows about it. King decides that only after his death prince should get map which should lead prince to the Treasure of GOLD. King in which case is an outer function which gives life to inner function but makes sure that after its execution has ended inner function which is prince has access to treasure. Lets take a look at following code and represent it in technology way:

            var King = (function(){
                     var treasureMap = 'Map to treasure';
                     this.myPrince = function(){
                            alert(treasureMap);
                     }
                     return {
                            prince:this.myPrince
                    }         
             })();

In  above code King is class and has private variable treasureMap which is not exposed because the function has been executed as soon as it is defined (module pattern). Lets see if King has treasureMap:

                        alert(King.treasureMap); // Oops it comes as undefined 


which means king may have it but is not revealing it which fulfills our use case.

King left prince as successor, it will be interesting to see if prince knows about it or not because King is dead and cannot access treasureMap.

                        King.prince(); // Alerts 'Map to treasure' Hurray!

How this happened? Closure is the answer. King.prince is the inner function in King which knows about treasureMap and has access to it even though King has left the world. This is closure which enabled prince to retain King's treasureMap property even when King has returned from execution call.


Closure: Memory Leaks

Like any other good thing, closure comes with challenges too. As long as closures are active, this memory cannot be garbage collected. Therefore, closures can lead to memory leaks if not used well. Lets examine a use case where it can lead to memory leak. Most of the memory leak in JavaScript is due to circular reference between javascript object and DOM element. For e.g.

               <html>
               <body>
               <script type="text/javascript">
                              window.onload=function preProcess(){
                               var obj = document.getElementById("elId");
                               obj.onclick=function createLeak(){
                                              //Some processing
                                              alert("Adding leak");
                               };
                               obj.something=new Array(1000);
                              
               };
               </script>
               <button id=" elId ">Test Me</button>
               </body>
               </html>

In the above example on load of window function preProcess will  be executed which will create a new JavaScript object obj with reference to DOM element elId and the DOM element has reference to JavaScript object thereby creating a circular reference. It is important to break this circular reference in order to address memory leak from the code. Simplest way to achieve this is to set JavScript obj to null when that object is no more required.

               <html>
               <body>
               <script type="text/javascript">
                              window.onload=function preProcess(){
                               var obj = document.getElementById("elId");
                               obj.onclick=function  createLeak (){
                                              //Some processing
                                              alert("no leak");
                               };
                               obj.something=new Array(1000);
                               obj = null; // set the object to null to break circular reference
                              
               };
               </script>
               <button id=" elId">Test Me</button>
               </body>
               </html>

Server side programming in JavaScript with nodejs, expressjs, stylus, jade etc. makes efficient use of closure. In conclusion, a closure in JavaScript is like keeping a copy of the all local variables, just as they were when a function exited.

1 comment:

  1. Nice one.Very good simple explanantion for closure concept.Continue the good work

    ReplyDelete