Closures are inner functions that can access outer function's parameters. It is a combination of function and the environment it has created. A closure is a nested function which can access variables of its immediate lexical scope. Closures have variables of 3 scopes: its own variables, it’s access to outer function variables and global variables.
Nested functions can continue to access variables from outer function, even after outer function finished execution. The browser keeps the lexical environment and it’s variables in memory until there is an inner function referencing it. When the variables in outer function change, inner function has the reference of variable and accesses the latest value. Functions can be nested in more than one level.
When a function has another function inside it, an external reference is kept for the inner function or its reference is returned. Closures cannot access the this keyword and argument binding of external function unless it is stored in a variable.
Example with JavaScript closure
Working with closures on arrays can be deceiving when we do not understand the references and scopes in them. Consider an array of functions called funcs[]
in example below. They are all defined within the dispInt()
as anonymous functions. The aim of the function was to display numbers from 0-4. When funcs[]
is returned, ‘i’ value is 5. Hence all the funcs[]
return 5.
Example with JavaScript closures and arrays
<script>
function dispInt(){
var funcs = [];
for(var i=0; i< 5; i++){
funcs[i] = function(){ return i; };
}
return funcs;
}
var funcs = dispInt();
for(var j=0; j<5; j++){
document.write(funcs[j]()); // 5 5 5 5 5
}
</script>
The above example shows unexpected result because, closures access the reference of the variable and do not make private copies of them. The scope chain associated with the anonymous function is live and stores the value of 5 while exiting the loop. Hence to get the desired output in above function following modification is necessary:
<script>
function dispInt(){
var funcs = [];
for(var i=0;i<5; i++){
funcs[i] = arrFunc(i);
}
return funcs;
//The index is returned each time and stored in function array.
function arrFunc(j){
return function(){
return j;
};
}
var funcs = dispInt();
for(var i=0; i<5; i++)
document.write(funcs[i]()); //0 1 2 3 4
</script>
Memory leaks in a closure
Closures are huge cause of memory leaks in JavaScript when not handled right, because inner functions hold reference to outer function variables even after outer function terminates. Consider the example below:
Example of memory leaks by JavaScript closure
var logo = null;
var newLogo = function(){
var firstLogo = logo;
logo = {
logoDesign : new Array(10000).join(“*$%^*”);
someMethod : function(){
//code which might use logo
}
}
// Avoids memory leaks as there is no big value linked to it.
firstLogo = null;
}
setInterval(newLogo, 1000);
If someMethod
is indirectly using firstLogo
for some evaluation in eval()
or has the firstLogo
in it’s lexical scoping, the firstLogo
is prevented from garbage collecting even after the function execution ended. Refreshing browser often, will lead to reduced performance because of large values stored in firstLogo
leading to a memory leak. Hence making the variables which comes in lexical scoping as null at the end of function, prevents accumulation of large values and memory leak (object de-referencing).
Comments
No comments have been made yet.
Please login to leave a comment. Login now