How do JavaScript closures work?

How do JavaScript closures work?

How would you explain JavaScript closures to someone with a knowledge of the concepts they consist of (for example functions, variables and the like), but does not understand closures themselves?
I have seen the Scheme example given on Wikipedia, but unfortunately it did not help.

Solutions/Answers:

Solution 1:

JavaScript closures for beginners

Submitted by Morris on Tue, 2006-02-21 10:19. Community-edited since.

Closures are not magic

This page explains closures so that a programmer can understand them — using working JavaScript code. It is not for gurus or functional programmers.

Closures are not hard to understand once the core concept is grokked. However, they are impossible to understand by reading any theoretical or academically oriented explanations!

This article is intended for programmers with some programming experience in a mainstream language, and who can read the following JavaScript function:

function sayHello(name) {
  var text = 'Hello ' + name;
  var say = function() { console.log(text); }
  say();
}
sayHello('Joe');

Two brief summaries

  • When a function (foo) declares other functions (bar and baz), the family of local variables created in foo is not destroyed when the function exits. The variables merely become invisible to the outside world. foo can therefore cunningly return the functions bar and baz, and they can continue to read, write and communicate with each other through this closed-off family of variables (“the closure”) that nobody else can meddle with, not even someone who calls foo again in future.

  • A closure is one way of supporting first-class functions; it is an expression that can reference variables within its scope (when it was first declared), be assigned to a variable, be passed as an argument to a function, or be returned as a function result.

An example of a closure

The following code returns a reference to a function:

function sayHello2(name) {
  var text = 'Hello ' + name; // Local variable
  var say = function() { console.log(text); }
  return say;
}
var say2 = sayHello2('Bob');
say2(); // logs "Hello Bob"

Most JavaScript programmers will understand how a reference to a function is returned to a variable (say2) in the above code. If you don’t, then you need to look at that before you can learn closures. A programmer using C would think of the function as returning a pointer to a function, and that the variables say and say2 were each a pointer to a function.

There is a critical difference between a C pointer to a function and a JavaScript reference to a function. In JavaScript, you can think of a function reference variable as having both a pointer to a function as well as a hidden pointer to a closure.

The above code has a closure because the anonymous function function() { console.log(text); } is declared inside another function, sayHello2() in this example. In JavaScript, if you use the function keyword inside another function, you are creating a closure.

In C and most other common languages, after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed.

In JavaScript, if you declare a function within another function, then the local variables of the outer function can remain accessible after returning from it. This is demonstrated above, because we call the function say2() after we have returned from sayHello2(). Notice that the code that we call references the variable text, which was a local variable of the function sayHello2().

function() { console.log(text); } // Output of say2.toString();

Looking at the output of say2.toString(), we can see that the code refers to the variable text. The anonymous function can reference text which holds the value 'Hello Bob' because the local variables of sayHello2() have been secretly kept alive in a closure.

The genius is that in JavaScript a function reference also has a secret reference to the closure it was created in — similar to how delegates are a method pointer plus a secret reference to an object.

More examples

For some reason, closures seem really hard to understand when you read about them, but when you see some examples, it becomes clear how they work (it took me a while).
I recommend working through the examples carefully until you understand how they work. If you start using closures without fully understanding how they work, you would soon create some very weird bugs!

Example 3

This example shows that the local variables are not copied — they are kept by reference. It is as though the stack-frame stays alive in memory even after the outer function exits!

function say667() {
  // Local variable that ends up within closure
  var num = 42;
  var say = function() { console.log(num); }
  num++;
  return say;
}
var sayNumber = say667();
sayNumber(); // logs 43

Example 4

All three global functions have a common reference to the same closure because they are all declared within a single call to setupSomeGlobals().

var gLogNumber, gIncreaseNumber, gSetNumber;
function setupSomeGlobals() {
  // Local variable that ends up within closure
  var num = 42;
  // Store some references to functions as global variables
  gLogNumber = function() { console.log(num); }
  gIncreaseNumber = function() { num++; }
  gSetNumber = function(x) { num = x; }
}

setupSomeGlobals();
gIncreaseNumber();
gLogNumber(); // 43
gSetNumber(5);
gLogNumber(); // 5

var oldLog = gLogNumber;

setupSomeGlobals();
gLogNumber(); // 42

oldLog() // 5

The three functions have shared access to the same closure — the local variables of setupSomeGlobals() when the three functions were defined.

Note that in the above example, if you call setupSomeGlobals() again, then a new closure (stack-frame!) is created. The old gLogNumber, gIncreaseNumber, gSetNumber variables are overwritten with new functions that have the new closure. (In JavaScript, whenever you declare a function inside another function, the inside function(s) is/are recreated again each time the outside function is called.)

Example 5

This example shows that the closure contains any local variables that were declared inside the outer function before it exited. Note that the variable alice is actually declared after the anonymous function. The anonymous function is declared first and when that function is called it can access the alice variable because alice is in the same scope (JavaScript does variable hoisting).
Also sayAlice()() just directly calls the function reference returned from sayAlice() — it is exactly the same as what was done previously but without the temporary variable.

function sayAlice() {
    var say = function() { console.log(alice); }
    // Local variable that ends up within closure
    var alice = 'Hello Alice';
    return say;
}
sayAlice()();// logs "Hello Alice"

Tricky: note the say variable is also inside the closure and could be accessed by any other function that might be declared within sayAlice(), or it could be accessed recursively within the inside function.

Example 6

This one is a real gotcha for many people, so you need to understand it. Be very careful if you are defining a function within a loop: the local variables from the closure may not act as you might first think.

You need to understand the “variable hoisting” feature in Javascript in order to understand this example.

function buildList(list) {
    var result = [];
    for (var i = 0; i < list.length; i++) {
        var item = 'item' + i;
        result.push( function() {console.log(item + ' ' + list[i])} );
    }
    return result;
}

function testList() {
    var fnlist = buildList([1,2,3]);
    // Using j only to help prevent confusion -- could use i.
    for (var j = 0; j < fnlist.length; j++) {
        fnlist[j]();
    }
}

 testList() //logs "item2 undefined" 3 times

The line result.push( function() {console.log(item + ' ' + list[i])} adds a reference to an anonymous function three times to the result array. If you are not so familiar with anonymous functions think of it like:

pointer = function() {console.log(item + ' ' + list[i])};
result.push(pointer);

Note that when you run the example, "item2 undefined" is logged three times! This is because just like previous examples, there is only one closure for the local variables for buildList (which are result, i, list and item). When the anonymous functions are called on the line fnlist[j](); they all use the same single closure, and they use the current value for i and item within that one closure (where i has a value of 3 because the loop had completed, and item has a value of 'item2'). Note we are indexing from 0 hence item has a value of item2. And the i++ will increment i to the value 3.

It may be helpful to see what happens when a block-level declaration of the variable item is used (via the let keyword) instead of a function-scoped variable declaration via the var keyword. If that change is made, then each anonymous function in the array result has its own closure; when the example is run the output is as follows:

item0 undefined
item1 undefined
item2 undefined

If the variable i is also defined using let instead of var, then the output is:

item0 1
item1 2
item2 3

Example 7

In this final example, each call to the main function creates a separate closure.

function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        console.log('num: ' + num +
            '; anArray: ' + anArray.toString() +
            '; ref.someVar: ' + ref.someVar + ';');
      }
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

Summary

If everything seems completely unclear, then the best thing to do is to play with the examples. Reading an explanation is much harder than understanding examples.
My explanations of closures and stack-frames, etc. are not technically correct — they are gross simplifications intended to help to understand. Once the basic idea is grokked, you can pick up the details later.

Final points:

  • Whenever you use function inside another function, a closure is used.
  • Whenever you use eval() inside a function, a closure is used. The text you eval can reference local variables of the function, and within eval you can even create new local variables by using eval('var foo = …')
  • When you use new Function(…) (the Function constructor) inside a function, it does not create a closure. (The new function cannot reference the local variables of the outer function.)
  • A closure in JavaScript is like keeping a copy of all the local variables, just as they were when a function exited.
  • It is probably best to think that a closure is always created just an entry to a function, and the local variables are added to that closure.
  • A new set of local variables is kept every time a function with a closure is called (given that the function contains a function declaration inside it, and a reference to that inside function is either returned or an external reference is kept for it in some way).
  • Two functions might look like they have the same source text, but have completely different behavior because of their ‘hidden’ closure. I don’t think JavaScript code can actually find out if a function reference has a closure or not.
  • If you are trying to do any dynamic source code modifications (for example: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola'));), it won’t work if myFunction is a closure (of course, you would never even think of doing source code string substitution at runtime, but…).
  • It is possible to get function declarations within function declarations within functions… and you can get closures at more than one level.
  • I think normally a closure is a term for both the function along with the variables that are captured. Note that I do not use that definition in this article!
  • I suspect that closures in JavaScript differ from those normally found in functional languages.

Links

Thanks

If you have just learned closures (here or elsewhere!), then I am interested in any feedback from you about any changes you might suggest that could make this article clearer. Send an email to morrisjohns.com (morris_closure @). Please note that I am not a guru on JavaScript — nor on closures.


Original post by Morris can be found in the Internet Archive.

Solution 2:

Whenever you see the function keyword within another function, the inner function has access to variables in the outer function.

function foo(x) {
  var tmp = 3;

  function bar(y) {
    console.log(x + y + (++tmp)); // will log 16
  }

  bar(10);
}

foo(2);

This will always log 16, because bar can access the x which was defined as an argument to foo, and it can also access tmp from foo.

That is a closure. A function doesn’t have to return in order to be called a closure. Simply accessing variables outside of your immediate lexical scope creates a closure.

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + (++tmp)); // will also log 16
  }
}

var bar = foo(2); // bar is now a closure.
bar(10);

The above function will also log 16, because bar can still refer to x and tmp, even though it is no longer directly inside the scope.

However, since tmp is still hanging around inside bar‘s closure, it is also being incremented. It will be incremented each time you call bar.

The simplest example of a closure is this:

var a = 10;

function test() {
  console.log(a); // will output 10
  console.log(b); // will output 6
}
var b = 6;
test();

When a JavaScript function is invoked, a new execution context is created. Together with the function arguments and the parent object, this execution context also receives all the variables declared outside of it (in the above example, both ‘a’ and ‘b’).

It is possible to create more than one closure function, either by returning a list of them or by setting them to global variables. All of these will refer to the same x and the same tmp, they don’t make their own copies.

Here the number x is a literal number. As with other literals in JavaScript, when foo is called, the number x is copied into foo as its argument x.

On the other hand, JavaScript always uses references when dealing with objects. If say, you called foo with an object, the closure it returns will reference that original object!

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + tmp);
    x.memb = x.memb ? x.memb + 1 : 1;
    console.log(x.memb);
  }
}

var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);

As expected, each call to bar(10) will increment x.memb. What might not be expected, is that x is simply referring to the same object as the age variable! After a couple of calls to bar, age.memb will be 2! This referencing is the basis for memory leaks with HTML objects.

Solution 3:

FOREWORD: this answer was written when the question was:

Like the old Albert said : “If you can’t explain it to a six-year old, you really don’t understand it yourself.”. Well I tried to explain JS closures to a 27 years old friend and completely failed.

Can anybody consider that I am 6 and strangely interested in that subject ?

I’m pretty sure I was one of the only people that attempted to take the initial question literally. Since then, the question has mutated several times, so my answer may now seem incredibly silly & out of place. Hopefully the general idea of the story remains fun for some.


I’m a big fan of analogy and metaphor when explaining difficult concepts, so let me try my hand with a story.

Once upon a time:

There was a princess…

function princess() {

She lived in a wonderful world full of adventures. She met her Prince Charming, rode around her world on a unicorn, battled dragons, encountered talking animals, and many other fantastical things.

    var adventures = [];

    function princeCharming() { /* ... */ }

    var unicorn = { /* ... */ },
        dragons = [ /* ... */ ],
        squirrel = "Hello!";

    /* ... */

But she would always have to return back to her dull world of chores and grown-ups.

    return {

And she would often tell them of her latest amazing adventure as a princess.

        story: function() {
            return adventures[adventures.length - 1];
        }
    };
}

But all they would see is a little girl…

var littleGirl = princess();

…telling stories about magic and fantasy.

littleGirl.story();

And even though the grown-ups knew of real princesses, they would never believe in the unicorns or dragons because they could never see them. The grown-ups said that they only existed inside the little girl’s imagination.

But we know the real truth; that the little girl with the princess inside…

…is really a princess with a little girl inside.

Solution 4:

Taking the question seriously, we should find out what a typical 6-year-old is capable of cognitively, though admittedly, one who is interested in JavaScript is not so typical.

On Childhood Development: 5 to 7 Years it says:

Your child will be able to follow two-step directions. For example, if you say to your child, “Go to the kitchen and get me a trash bag” they will be able to remember that direction.

We can use this example to explain closures, as follows:

The kitchen is a closure that has a local variable, called trashBags. There is a function inside the kitchen called getTrashBag that gets one trash bag and returns it.

We can code this in JavaScript like this:

function makeKitchen() {
  var trashBags = ['A', 'B', 'C']; // only 3 at first

  return {
    getTrashBag: function() {
      return trashBags.pop();
    }
  };
}

var kitchen = makeKitchen();

console.log(kitchen.getTrashBag()); // returns trash bag C
console.log(kitchen.getTrashBag()); // returns trash bag B
console.log(kitchen.getTrashBag()); // returns trash bag A

Further points that explain why closures are interesting:

  • Each time makeKitchen() is called, a new closure is created with its own separate trashBags.
  • The trashBags variable is local to the inside of each kitchen and is not accessible outside, but the inner function on the getTrashBag property does have access to it.
  • Every function call creates a closure, but there would be no need to keep the closure around unless an inner function, which has access to the inside of the closure, can be called from outside the closure. Returning the object with the getTrashBag function does that here.

Solution 5:

The Straw Man

I need to know how many times a button has been clicked and do something on every third click…

Fairly Obvious Solution

// Declare counter outside event handler's scope
var counter = 0;
var element = document.getElementById('button');

element.addEventListener("click", function() {
  // Increment outside counter
  counter++;

  if (counter === 3) {
    // Do something every third time
    console.log("Third time's the charm!");

    // Reset counter
    counter = 0;
  }
});
<button id="button">Click Me!</button>

Now this will work, but it does encroach into the outer scope by adding a variable, whose sole purpose is to keep track of the count. In some situations, this would be preferable as your outer application might need access to this information. But in this case, we are only changing every third click’s behavior, so it is preferable to enclose this functionality inside the event handler.

Consider this option

var element = document.getElementById('button');

element.addEventListener("click", (function() {
  // init the count to 0
  var count = 0;

  return function(e) { // <- This function becomes the click handler
    count++; //    and will retain access to the above `count`

    if (count === 3) {
      // Do something every third time
      console.log("Third time's the charm!");

      //Reset counter
      count = 0;
    }
  };
})());
<button id="button">Click Me!</button>

Notice a few things here.

In the above example, I am using the closure behavior of JavaScript. This behavior allows any function to have access to the scope in which it was created, indefinitely. To practically apply this, I immediately invoke a function that returns another function, and because the function I’m returning has access to the internal count variable (because of the closure behavior explained above) this results in a private scope for usage by the resulting function… Not so simple? Let’s dilute it down…

A simple one-line closure

//          _______________________Immediately invoked______________________
//         |                                                                |
//         |        Scope retained for use      ___Returned as the____      |
//         |       only by returned function   |    value of func     |     |
//         |             |            |        |                      |     |
//         v             v            v        v                      v     v
var func = (function() { var a = 'val'; return function() { alert(a); }; })();

All variables outside the returned function are available to the returned function, but they are not directly available to the returned function object…

func();  // Alerts "val"
func.a;  // Undefined

Get it? So in our primary example, the count variable is contained within the closure and always available to the event handler, so it retains its state from click to click.

Also, this private variable state is fully accessible, for both readings and assigning to its private scoped variables.

There you go; you’re now fully encapsulating this behavior.

Full Blog Post (including jQuery considerations)

Solution 6:

Closures are hard to explain because they are used to make some behaviour work that everybody intuitively expects to work anyway. I find the best way to explain them (and the way that I learned what they do) is to imagine the situation without them:

    var bind = function(x) {
        return function(y) { return x + y; };
    }
    
    var plus5 = bind(5);
    console.log(plus5(3));

What would happen here if JavaScript didn’t know closures? Just replace the call in the last line by its method body (which is basically what function calls do) and you get:

console.log(x + 3);

Now, where’s the definition of x? We didn’t define it in the current scope. The only solution is to let plus5 carry its scope (or rather, its parent’s scope) around. This way, x is well-defined and it is bound to the value 5.