Who is this article intended for?
All folks who are working with JavaScript, learning JavaScript, or have been using fancy JavaScript frameworks and platforms like AngularJS, NodeJS or even as basic as jQuery or if you plan to start writing JavaScript and transitioning from object-oriented languages like C# or you are a reader and like reading non-fiction articles.
JavaScript
JavaScript is the most forgiving language I have ever come across. Everything just seems to work, well this can be dangerous, sometimes - if not always; we might end up writing something that works but may be very inefficient or even worst, after a long day’s work, the script might seem perfect but the output may be equally bizarre. I agree that JavaScript may be unintuitive, occasionally, even counterintuitive. Let’s look at the following example to see what I mean.
JavaScript
- 'use strict'
- for(var i = 0; i < 10; i++) {
- console.log('"i" is equal to ' + i);
- }
- //Code 1.0
Can you guess what output will it produce? You guessed it right.
It will produce the following output,
- "i" is equal to 0
- "i" is equal to 1
- "i" is equal to 2
- "i" is equal to 3
- "i" is equal to 4
- "i" is equal to 5
- "i" is equal to 6
- "i" is equal to 7
- "i" is equal to 8
- "i" is equal to 9
- //Output 1.0
JavaScript
- 'use strict'
- for(var i = 0; i < 10; i++) {
- setTimeout(function() {
- console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
- }, (1000 * i));
- }
- //Code 1.1
And you would be expecting following output,
- "i" is equal to 0 (after 0 secs)
- "i" is equal to 1 (after 1 secs)
- "i" is equal to 2 (after 2 secs)
- "i" is equal to 3 (after 3 secs)
- "i" is equal to 4 (after 4 secs)
- "i" is equal to 5 (after 5 secs)
- "i" is equal to 6 (after 6 secs)
- "i" is equal to 7 (after 7 secs)
- "i" is equal to 8 (after 8 secs)
- "i" is equal to 9 (after 9 secs)
- //Assumed Output 1.1
Above code will actually produce following output.
Bizarre right? Didn’t I say that javascript can be counterintuitive sometimes!
What just happened? – Well, Meet Closure!
What you just encountered is called closure. Well, Don’t be rude, say hello! Closure is a friend if understood and used wisely but a fearful enemy if left unnoticed.
Closure enables functions to remember its scope of execution. Meaning, it makes functions remember the variables and other functions it refers to. Closure makes the referred variables and functions available, even after the scope is exited, latest values are reflected. The simplest example of closure is following hello world example,
JavaScript
- 'use strict'
- //Following function returns a function which prints - Hello `name`!
- function sayHelloTo(name) {
- return function() {
- //This function "remembers" the name -- thanks to closure.
- console.log('Hello ' + name + '!');
- }
- }
- var helloWorld = sayHelloTo('World');
- /* The closure enables the child function "remember" the "name" variable even after the parent scope has exited. */
- //Prints out "Hello World!" in the console.
- helloWorld();
- //Code 1.2
- Hello World! //output 1.2
Pretty neat right? And this is what happened with our first example, closure. A little bit cryptic, ain’t it? Let me elaborate, javascript runs on a single thread, so it queues up tasks that need differed execution, remember setTimeout - we used it in our first example? So what happened with the example is first the for loop executes and iterates for 10 times with value of i = 0 to 9, with each iteration it executes setTimeout block with appropriate value of i, meaning for i = 0 => setTimeout(<function>,0) for i = 1 => setTimeout(<function>,1000) and for i = 9 => setTimeout(<function>,9000).
Now setTimeout is executed but the <function> goes through deferred execution, so the first <function> is executed only after the for loop is executed completely. So at the time when <function> executes, the for loop has already exited, and the final value is equal to 10. Now due to closure, <function> remembers the I and fetches the latest value, which is 10 and hence the cryptic output. What we learned is that the value of i is NOT COPIED for each iteration instead the reference is remembered.
How do I make it work then?
There is more than one way to get what we want. First let's look at IIFE.
Option 1: IIFE
IIFE (immediately-invoked function expression) are function expressions that are executed as soon as they are defined. For example
JavaScript
- 'use strict'
- //The IIFE
- (function(arguments) {
- /* Awesomeness goes here */
- })();
- //Code 1.3
JavaScript
- 'use strict'
- for(var i = 0; i < 10; i++) {
- /* IIFE with a parameter i, this i parameter is different then i in
- the for loop. IIFE forces a new execution scope to be created
- and current *value* of the i in for loop is *copied* to the new
- scope
- */
- (function(i) {
- //i has *value* i (of for loop) at the time of invocation
- setTimeout(function() {
- console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
- }, (1000 * i));
- })(i); //i of the for loop is passed as parameter, forcing new scope to be
- //created with current copy of i.
- }
- //Code 1.1.1
Option 2: Function.prototype.bind
The above example with IIFE looks quite complex and mouthful. As we now have an idea on how to solve the problem on hand, all we need to do is force create new scope and Function.prototype.bind can be used to do so.
JavaScript
- 'use strict'
- for(var i = 0; i < 10; i++) {
- /*
- (<function(i)>).bind(this, i) forces a new scope to be created *copying*
- the current *value* of i
- */
- setTimeout((function(i) {
- console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
- }).bind(this, i), (1000 * i));
- }
- // Code 1.1.2
This version is very much similar to Code 1.1, only difference is instead of setTimeout(<function>,timeout) we have setTimeout( (<function(i)>).bind(this, i), timeout). So instead of asking setTimeout to defer <function> we are asking it to defer a copy of <function>bound to current value of i.
Option 3: The ES6 way!
Let is almost exactly same as var except the fact that it creates lexically scoped variables. Variables created declared with let have limited to the scope they are defined in, in case of for loop, for each iteration, new copy of i is created which limits to that particular iteration.
JavaScript
- 'use strict'
- /* We are using `let` instead of `var`, `let` creates a `lexically` scoped
- variable i, meaning, for each iteration of for loop a new copy of i is
- created, so closure captures the `lexically` scoped reference
- */
- for(let i = 0; i < 10; i++) {
- setTimeout(function() {
- console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
- }, (1000 * i));
- }
- // Code 1.1.3
All of these three options produce following output.
JavaScript
- "i"
- is equal to 0(after 0 secs)
- "i"
- is equal to 1(after 1 secs)
- "i"
- is equal to 2(after 2 secs)
- "i"
- is equal to 3(after 3 secs)
- "i"
- is equal to 4(after 4 secs)
- "i"
- is equal to 5(after 5 secs)
- "i"
- is equal to 6(after 6 secs)
- "i"
- is equal to 7(after 7 secs)
- "i"
- is equal to 8(after 8 secs)
- "i"
- is equal to 9(after 9 secs)
- // Output for 1.1.1, 1.1.2, 1.1.3
A word of Caution
As you can see, closures are powerful, but as uncle ben once said With great power comes great responsibility. Unnecessary usage of closure can make your code inefficient. Because every time a closure is created memory is consumed to store and maintain the references, sometimes this will result in a poor-quality program. So always make sure that you eliminate any unnecessary and unintended closures.
For example, one should not write functions inside functions and access parent functions values when there are better ways to do the same thing. Because doing so would create unnecessary closure. Take a look at the following example.

Amit DavePosted May 2, 2016, 6:48 AM
Thanks K P Singh Chundawat and Sonu Chaudhary
Sonu ChaudharyPosted May 2, 2016, 5:53 AM
Thanks for sharing
K P Singh ChundawatPosted May 2, 2016, 2:49 AM
Very Good Article and Thanks for Sharing .
Amit DavePosted May 2, 2016, 2:45 AM
Thanks Sanjay Gupta
Sanjay GuptaPosted May 2, 2016, 1:37 AM
Nice Explanation of tough subject.
Amit DavePosted May 1, 2016, 6:57 PM
Thanks Kuppurasu Nagaraj, Nitin Tyagi and Debasis Saha
Debasis SahaPosted May 1, 2016, 1:50 PM
Good One..
NitinPosted May 1, 2016, 1:45 PM
Good one
Kuppurasu NagarajPosted May 1, 2016, 12:45 PM
Nice Sharing..