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.
Closure: Memory Leaks
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.
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.
Nice one.Very good simple explanantion for closure concept.Continue the good work
ReplyDelete