Closures in JavaScript

Closures in JavaScript can be considered as functions that persist. It's a language feature where an inner function has access to all variables defined in a parent function even after parent function execution context is popped off the execution stack.

Let's see few examples and try to understand it in detail.

<script type="text/javascript">
		
		var incrementSalary = function(amount){
		  var current = 0;
		  /**
		  return inner function which increment the current value
		  by the amount passed as parameter

		  */
		  return function(){
		     current+=amount;
		     return current;
		   }
		}
		var incr =  incrementSalary(5000)// hold the inner function
		console.log(incr()); 5000
		console.log(incr()); 10000
		console.log(incr()); 15000
</script>

 

The above JavaScript code has a function expression incrementSalary which returns a function that increments the current amount to the amount passed as a parameter.

At #15 incrementSalary is invoked which returns an anonymous function which has access to the outer function variable current even after the parent function has finished execution.

Let's look into another classic example of closures which has to deal with for loops.

 

<script type="text/javascipt">

       var demoFunction = function(){

        	var listOfFunction = [];

        	for(var i=0; i<5 ;i++){
               
               listOfFunction.push(
               	function(){console.log(i)}
               	)
        	}

         return listOfFunction;  
       }
       
       var functions = demoFunction();
       functions[0]() // 5
       functions[1]() // 5
       functions[2]() // 5
       functions[3]() // 5
       functions[4]() // 5   
</script>

 

The above code is an another example for exploring the closures, let's go through it line by line.

#5 defines an array for pushing the function into it.

#9 to #12 pushes the function into it, remember we are just pushing the function not executing it.

#14  returns the array and #17 invokes the function which returns the array of functions.

#18 to #22 invokes the function which was pushed into it, normally the expected output would be from 0 to 4 but the actual output is different than expected which is 5 for all the function call.

The explanation for the above behavior:

Once the demoFunction at #17 finishes execution the variable i has the value set to 5 which breaks the for loop condition.

So whenever the function within the array is invoked, due to the scope chain it has access to the variable i whose value to set to 5.

Since all the function were created at the same place they all point to the same outer environment.

Let's see how can we get the expected behavior

1:  ES6 has introduced a new keyword let which creates block scope for variables.

   Replace #7 of the above code sample to the mentioned below one.

for(let i=0; i<5 ;i++){

  

2: IIFE can be used for creating an execution context on the fly by immediately invoking a function expression, this way we can preserve the different value of i at different execution context.

Replace #9 to #11 with the mentioned below code.

listOfFunction.push(
/**
  here the function is immediately invoked for 
  different values of i and passed to j,
  finally return a function which has access to j. 
  Hence the scope chain need not go all way to for loop, it will find the 
  value of j where the IIFE was defined.    
*/
   (function(j){
       return function(){
         console.log(j);
        }
   }(i))
)

 

Thanks for reading.