579

A friend of mine and I are currently discussing what is a closure in JS and what isn't. We just want to make sure we really understand it correctly.

Let's take this example. We have a counting loop and want to print the counter variable on the console delayed. Therefore we use setTimeout and closures to capture the value of the counter variable to make sure that it will not print N times the value N.

The wrong solution without closures or anything near to closures would be:

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

which will of course print 10 times the value of i after the loop, namely 10.

So his attempt was:

for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i;
        setTimeout(function(){
            console.log(i2);
        }, 1000)
    })();
}

printing 0 to 9 as expected.

I told him that he isn't using a closure to capture i, but he insists that he is. I proved that he doesn't use closures by putting the for loop body within another setTimeout (passing his anonymous function to setTimeout), printing 10 times 10 again. The same applies if I store his function in a var and execute it after the loop, also printing 10 times 10. So my argument is that he doesn't really capture the value of i, making his version not a closure.

My attempt was:

for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2);
        }
    })(i), 1000);
}

So I capture i (named i2 within the closure), but now I return another function and pass this around. In my case, the function passed to setTimeout really captures i.

Now who is using closures and who isn't?

Note that both solutions print 0 to 9 on the console delayed, so they solve the original problem, but we want to understand which of those two solutions uses closures to accomplish this.

Azeezah M
  • 144
  • 1
  • 9
leemes
  • 44,967
  • 21
  • 135
  • 183
  • 15
    These might be useful: [What is the difference between a 'closure' and a 'lambda'?](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) and [What is a Lambda?](http://stackoverflow.com/questions/150129/what-is-a-lambda) – Blender Oct 17 '12 at 08:41
  • @Blender Thanks for the link. I think he uses a lambda function and I use a closure. Is this correct? – leemes Oct 17 '12 at 08:43
  • 1
    @leemes: See my ninja edit for a second link. – Blender Oct 17 '12 at 08:44
  • 2
    we just made up a deal: the one who's right is going to get the SO points related to this question – brillout Oct 17 '12 at 08:48
  • @leemes: I have a feeling that your attempt isn't actually a closure. You are passing `i` in through an argument, which is different than grabbing it from the parent's scope. – Blender Oct 17 '12 at 09:09
  • @Blender My closure is the returned function, not the wrapper. – leemes Oct 17 '12 at 09:14
  • 1
    @leemes - Both of you are using closures. Both of you have made two functions - an outer function and an inner function; and both of your inner functions are closures. All of your functions are lambdas ([anonymous functions](http://en.wikipedia.org/wiki/Anonymous_function "Anonymous function - Wikipedia, the free encyclopedia")). Read my answer for the details. – Aadit M Shah Oct 17 '12 at 10:27
  • @brillout.com - Since the two of you tied may I get the SO points related to this question? – Aadit M Shah Oct 17 '12 at 10:29
  • @AaditMShah I'll give you some bounty, but this is only possible in two days I think. – leemes Oct 17 '12 at 10:47
  • The terms "closure" and "modified closure" cause semantic confusion between developers at times I think. As a lot of people have run into errors caused by "[access to a modified closure](http://stackoverflow.com/questions/235455/access-to-modified-closure)" and it causes them to think a "closure" is something entirely different than what it actually is. – Ben Lesh Oct 17 '12 at 13:29
  • There's a better way to do this in Javascript, but it doesn't exactly involve closures: `for(...) { with({i: i}) { setTimeout(function() {console.log(i);}, 1000); } }` – Izkata Oct 17 '12 at 14:16
  • 1
    @blesh - I have no idea what a modified closure is. I see that your link points to C# code. Are modified closures supported by JavaScript? – Aadit M Shah Oct 17 '12 at 15:41
  • 1
    Modified closure is a bit of a misnomer of a name. Basically the first example of the OP illustrates a modified closure. That would be where you have some free variable that is altered prior to some inner method accessing. For example `i` from a `for` loop being accessed inside the `setTimeout` in the first example. It's modified to be 10 by the time any of the timeout callbacks execute. – Ben Lesh Oct 17 '12 at 15:46
  • It actually seems to be terminology introduced by JetBrains in R#. But I've known people to use it to describe the same situation in other languages. – Ben Lesh Oct 17 '12 at 15:49
  • 1
    @Izkata - That's debatable. Using `with` adds a new lexical scope to the scope chain. This is similar to calling a new function. Remember that a "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression). What this "environment" must be is not specifically defined. Thus I believe it's safe to assume that even by using `with` instead of an outer function a closure is created. Intuitively even the global scope is not the scope of a function. It's just a lexical scope, just like `with`. – Aadit M Shah Oct 17 '12 at 15:53
  • @blesh - Ah. That makes sense. Classic JavaScript problem for beginners. So, if I'm not mistaken, the criterion for a language to support modified closures is that it must not support block scoping. Am I correct? – Aadit M Shah Oct 17 '12 at 15:57
  • It would have to support some sort of lexical scoping. – Ben Lesh Oct 17 '12 at 16:04
  • 1
    @AaditMShah I've never been sure what to call a closure and what not to, but I'd think using `with` isn't, even though it starts a new scope, because in that example you're in the scope of an anonymous hash/object. As far as I recall, usually object-level scopes don't count.. Or is an object (which isn't a series of expressions, but a hash of attributes) an expression itself? =) – Izkata Oct 17 '12 at 16:30
  • @blesh - Lexical scoping without any block scoping. Like in JavaScript. =) – Aadit M Shah Oct 17 '12 at 16:35
  • @Izkata - When you use `with` you're in a proper lexical scope. If you were in an "object scope" then you would only be able to access the properties of the object (in your case only `i`) and the properties on the prototype chain of the object (which means you would be able to access things like `hasOwnProperty` directly - which is obviously wrong behavior). You wouldn't be able to access variables in parent scopes like `setTimeout` (which you are accessing) because they wouldn't be on the prototype chain of the object passed to `with`. That's why I believe that it's still a closure. – Aadit M Shah Oct 17 '12 at 16:39
  • @Izkata - You just gave me a brilliant idea to implement sandboxing in JavaScript using `with`. Let's see where that takes me. =) – Aadit M Shah Oct 17 '12 at 16:41
  • better question to this would have been who as using an 'IIFE' – Anthony Chua Jan 09 '14 at 16:33

12 Answers12

671

Editor's Note: All functions in JavaScript are closures as explained in this post. However we are only interested in identifying a subset of these functions which are interesting from a theoretical point of view. Henceforth any reference to the word closure will refer to this subset of functions unless otherwise stated.

A simple explanation for closures:

  1. Take a function. Let's call it F.
  2. List all the variables of F.
  3. The variables may be of two types:
    1. Local variables (bound variables)
    2. Non-local variables (free variables)
  4. If F has no free variables then it cannot be a closure.
  5. If F has any free variables (which are defined in a parent scope of F) then:
    1. There must be only one parent scope of F to which a free variable is bound.
    2. If F is referenced from outside that parent scope, then it becomes a closure for that free variable.
    3. That free variable is called an upvalue of the closure F.

Now let's use this to figure out who uses closures and who doesn't (for the sake of explanation I have named the functions):

Case 1: Your Friend's Program

for (var i = 0; i < 10; i++) {
    (function f() {
        var i2 = i;
        setTimeout(function g() {
            console.log(i2);
        }, 1000);
    })();
}

In the above program there are two functions: f and g. Let's see if they are closures:

For f:

  1. List the variables:
    1. i2 is a local variable.
    2. i is a free variable.
    3. setTimeout is a free variable.
    4. g is a local variable.
    5. console is a free variable.
  2. Find the parent scope to which each free variable is bound:
    1. i is bound to the global scope.
    2. setTimeout is bound to the global scope.
    3. console is bound to the global scope.
  3. In which scope is the function referenced? The global scope.
    1. Hence i is not closed over by f.
    2. Hence setTimeout is not closed over by f.
    3. Hence console is not closed over by f.

Thus the function f is not a closure.

For g:

  1. List the variables:
    1. console is a free variable.
    2. i2 is a free variable.
  2. Find the parent scope to which each free variable is bound:
    1. console is bound to the global scope.
    2. i2 is bound to the scope of f.
  3. In which scope is the function referenced? The scope of setTimeout.
    1. Hence console is not closed over by g.
    2. Hence i2 is closed over by g.

Thus the function g is a closure for the free variable i2 (which is an upvalue for g) when it's referenced from within setTimeout.

Bad for you: Your friend is using a closure. The inner function is a closure.

Case 2: Your Program

for (var i = 0; i < 10; i++) {
    setTimeout((function f(i2) {
        return function g() {
            console.log(i2);
        };
    })(i), 1000);
}

In the above program there are two functions: f and g. Let's see if they are closures:

For f:

  1. List the variables:
    1. i2 is a local variable.
    2. g is a local variable.
    3. console is a free variable.
  2. Find the parent scope to which each free variable is bound:
    1. console is bound to the global scope.
  3. In which scope is the function referenced? The global scope.
    1. Hence console is not closed over by f.

Thus the function f is not a closure.

For g:

  1. List the variables:
    1. console is a free variable.
    2. i2 is a free variable.
  2. Find the parent scope to which each free variable is bound:
    1. console is bound to the global scope.
    2. i2 is bound to the scope of f.
  3. In which scope is the function referenced? The scope of setTimeout.
    1. Hence console is not closed over by g.
    2. Hence i2 is closed over by g.

Thus the function g is a closure for the free variable i2 (which is an upvalue for g) when it's referenced from within setTimeout.

Good for you: You are using a closure. The inner function is a closure.

So both you and your friend are using closures. Stop arguing. I hope I cleared the concept of closures and how to identify them for the both of you.

Edit: A simple explanation as to why are all functions closures (credits @Peter):

First let's consider the following program (it's the control):

lexicalScope();

function lexicalScope() {
    var message = "This is the control. You should be able to see this message being alerted.";

    regularFunction();

    function regularFunction() {
        alert(eval("message"));
    }
}
  1. We know that both lexicalScope and regularFunction aren't closures from the above definition.
  2. When we execute the program we expect message to be alerted because regularFunction is not a closure (i.e. it has access to all the variables in its parent scope - including message).
  3. When we execute the program we observe that message is indeed alerted.

Next let's consider the following program (it's the alternative):

var closureFunction = lexicalScope();

closureFunction();

function lexicalScope() {
    var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure.";

    return function closureFunction() {
        alert(eval("message"));
    };
}
  1. We know that only closureFunction is a closure from the above definition.
  2. When we execute the program we expect message not to be alerted because closureFunction is a closure (i.e. it only has access to all its non-local variables at the time the function is created (see this answer) - this does not include message).
  3. When we execute the program we observe that message is actually being alerted.

What do we infer from this?

  1. JavaScript interpreters do not treat closures differently from the way they treat other functions.
  2. Every function carries its scope chain along with it. Closures don't have a separate referencing environment.
  3. A closure is just like every other function. We just call them closures when they are referenced in a scope outside the scope to which they belong because this is an interesting case.
Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • 42
    Accepted because you go very much in details, explaining very nice what's going on. And finally, I now understood better what a closure is, or better said: how variable binding works in JS. – leemes Oct 17 '12 at 10:34
  • 3
    In Case 1, you say that `g` runs in the scope of `setTimeout`, but in Case 2 you say that `f` runs in the global scope. They are both within setTimeout, so what is the difference? – rosscj2533 Oct 17 '12 at 14:05
  • 2
    In case 1 `g` is passed as a parameter to `setTimeout`. Thus `g` is executed in the scope of `setTimeout`. In case 2 `f` appears to be passed as a parameter to `setTimeout`, but remember that `f` is invoked immediately with the argument `i`. Thus it's executed in the global scope, and the value returned by `f` (which is `g`) is actually being passed as the argument to `setTimeout`. Thus `g` is executed in the scope of `setTimeout`. – Aadit M Shah Oct 17 '12 at 14:10
  • 1
    @AaditMShah, ah, I see now, great explanation and great answer. I'll upvote tomorrow so you actually get the reputation :) – rosscj2533 Oct 17 '12 at 14:22
  • 11
    Will you please state your sources for this? I've never seen a definition where a function could be a closure if called in one scope but not in another. Thus, this definition seems like a subset of the more general definition I'm used to (see [kev's answer](http://stackoverflow.com/a/12930641/508537)) where a closure is a closure is a closure regardless of the scope it is called, or even if it is never called! – Briguy37 Oct 17 '12 at 18:17
  • @Briguy37 - You are correct. While a function __is__ a closure when called in another scope, it's also a closure when simply referenced by another scope. Since referencing is more general than calling I edited my answer to reflect it. Now my definition should be at par with kev's answer. Thank you for pointing out the mistake. Appreciated. – Aadit M Shah Oct 17 '12 at 23:54
  • 2
    I think, as the term is commonly defined, `f` in the first program does in fact close over `i`. That is, `f` is in fact a closure over `i`. – danfuzz Oct 18 '12 at 03:51
  • @danfuzz - I don't see how. The variable `i` is a global and `f` itself exists in the global scope. It would be a closure if we moved `f` out of the global scope (say to another window perhaps). An example of this would be something like `window.top.f()`. What are your thoughts on this? Care to explain how you came to that conclusion? – Aadit M Shah Oct 18 '12 at 04:29
  • 2
    This answer is continuing to spread misinformation about closures in JavaScript. *EVERY* function in JavaScript forms a closure when it is created *PERIOD*. When a function is created, the referencing environment is always stored as part the function object using what is called a scope chain. I think people are confusing the difference between when a closure is useful and when it is not. – Peter Oct 18 '12 at 05:50
  • @Peter - I disagree. Variables in JavaScript have a lifetime which's limited to the scope to which they are bound. Thus when a variable goes out of scope it ceases to exist. Functions in JavaScript introduce a new lexical scope. Since JavaScript has first class functions they may be passed around just like variables. This is interesting because you're essentially passing around a scope & everything associated with it. When a function's referenced in the same scope it was declared in then there's no problem. When it goes out of scope it needs to take it's scope with it. That's called a closure. – Aadit M Shah Oct 18 '12 at 07:57
  • @Peter - If you want proof then view the following [MDN link](https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures "Closures - JavaScript | MDN"). It clearly states in the fifth paragraph that, and I quite verbatim, "The solution to this puzzle is that `myFunc` has become a _closure_". The words _"has become"_ clearly imply that `myFunc` was not a closure before the given context. I hope I've convinced you that my answer is not spreading misinformation about closures in JavaScript. – Aadit M Shah Oct 18 '12 at 08:08
  • @Peter - Just to differentiate: the scope chain is a series of __execution contexts__ which stores __every local variable__ in the scope as a property. A closure is a __single__ execution context (which only stores the local variables of the closure) along with a referencing environment (which is a table containing references to __only those variables which are non local variables of the closure__). See [Jon's answer](http://stackoverflow.com/a/12930799/783743) for more information. – Aadit M Shah Oct 18 '12 at 08:16
  • 13
    @AaditMShah I agree with you about what a closure is, but you speak as if there is a difference between *regular* functions and *closures* in JavaScript. There is no difference; internally every function will carry with it a reference to the particular scope chain in which it was created. The JS engine does not consider it a different case. There is no need for a complicated check-list; just know that every function object carries lexical scope. The fact that variables/properties are globally available does not make the function any less a closure (it's just a useless case). – Peter Oct 18 '12 at 19:16
  • @AaditMShah Here is a decent overview of some common myths surrounding closures with references to ECMA-262. http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/ – Peter Oct 18 '12 at 23:09
  • 15
    @Peter - You know what, you are correct. There's no difference between a regular function and a closure. I ran a test to prove this and it results in your favor: here's the [control](http://jsfiddle.net/KyQKw/) and here's the [alternative](http://jsfiddle.net/KyQKw/1/). What you say does make sense. The JavaScript interpreter need do special bookkeeping for closures. They are simply by-products of a lexically scoped language with first class functions. My knowledge was limited to what I read (which was false). Thank you for correcting me. I'll update my answer to reflect the same. – Aadit M Shah Oct 19 '12 at 03:16
  • 1
    @AaditMShah No worries, there's a lot of confusing information about closures all over the place. I like the way you describe closures as 'by-products of a lexically scoped language with first class functions' :). When you think about it this way, it's not all that complex after all. Great article you referenced about the scope chain by the way: http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain/ – Peter Oct 19 '12 at 05:42
  • @Peter - Would you mind removing the down vote now that my answer does not spread misinformation, please? – Aadit M Shah Oct 20 '12 at 14:19
  • @AaditMShah I can't, it's still locked-in for some reason :O. – Peter Oct 22 '12 at 17:29
  • @fatmatto - ninjutsu? Should I take that as a compliment? – Aadit M Shah Oct 23 '12 at 20:14
  • @AaditMShah - Great and very thorough article. Can you explain this line in 5(i) - "There must be only one parent scope of F to which a free variable is bound." Little confusion to me but can you give any example of two parent scope of F. Thanks – Anmol Saraf Oct 25 '12 at 10:56
  • 1
    @AnmolSaraf - It simply means that a variable is only local to one scope. For example, in the first program, consider the function `g`. The variable `i2` is a free variable in `g` (which means it's declared in a parent scope of `g`). A variable is only declared once. In this case `i2` is declared in `f` which is a parent scope of `g`. Thus `i2` is only local to `f`. It doesn't exist in the any parent scope of `f`, and it's not a local variable (but a free variable) in any scope which is a subset of `f` (like `g`). Thus if a variable is free in a given scope it's only local to one parent scope. – Aadit M Shah Oct 25 '12 at 14:35
  • @AaditMShah - thanks for the humble and detailed reply. Just one more query from your above lines, " if a variable is free in a given scope it's only local to one parent scope." Is it mandatory that the parent scope must be the immediate parent scope or can it be a parent of immediate parent i.e. Ancestor, like in the case where its a nesting of three functions one inside another ? Example - function C inside function B and function B inside function A, so now can function A be the parent scope for a free variable inside function C ? – Anmol Saraf Oct 25 '12 at 15:51
  • @AnmolSaraf - It may be any parent scope. So if `h` is inside `g` and `g` is inside `f`, and a variable `x` which is local to `f` is used in `h` then `h` only closes over `x` when `h` is referenced outside `f`. – Aadit M Shah Oct 25 '12 at 16:09
  • @AaditMShah - Thank you so much !! I understand this quite well now :) – Anmol Saraf Oct 25 '12 at 20:24
  • *"All functions in JavaScript are closures"* In fact so are all functions in C. The global scope in C is an environment of variables, and all functions can see both their own variables and the global environment's variables. The lifetime of the global environment is the lifetime of the whole program, so the garbage collection challenge goes away. Also there is only ever one instance of the global environment, so there is no need for each function invocation to store a pointer to it. It's the one case of closure where the implementation cost is zero, which is why it's the only kind C supports. – Daniel Earwicker Jun 21 '13 at 14:48
  • does global scope reference affect closure property? – internals-in Jul 21 '13 at 15:55
  • @7-isnotbad I not entirely sure about what you're asking, but functions can never close over global variables because the global scope is the topmost scope. Hence a function can never be referenced outside the global scope. – Aadit M Shah Jul 21 '13 at 15:59
  • +1 oh! i'm going back and forth till now to get the concept in ....... got it! thanks any way – internals-in Jul 21 '13 at 16:07
  • @Ankit Identifying closures is actually quite important in languages like Lua where closures are handled specially. The ECMAScript standard takes the easy way out and makes every function carry its lexical environment with it. The consequence is that closures aren't interesting in JavaScript. However, the concept of closures transcends JavaScript itself and understanding closures is essential for understanding other things like Hindley-Milner type inference. The paragon of the application of closures is the [runST](http://ow.ly/LlX03) function in Haskell which uses existential quantification. – Aadit M Shah Apr 08 '15 at 16:54
  • @Aadit : What exactly do you mean by closed over? For the Case1, and for function g, the free variable i2 is bounded to the scope of f, and the function g is bounded to the scope setTimeout. How is i2 closed over by g in this case. Request you to kindly extend a bit. – Farhan stands with Palestine Aug 27 '15 at 17:35
  • @Aadit: I failed to recognize how i2 is closed over by g. i2 is bounded to the scope of f and g is referenced in the scope setTimeout. And clearly the scope of f and setTimeout is same. Kindly suggest. – Farhan stands with Palestine Aug 28 '15 at 13:19
  • @ShirgillAnsari The scope of `f` and `setTimeout` are not the same. In case 1 and for function `g` the free variable `i2` is defined in the scope of `f`. Hence, it is bound to `f`. The function `g` is also defined in the scope of `f`. Hence, it has access to the variable `i2`. However, the function `setTimeout` doesn't have access to the variable `i2` because it is not defined in the scope of `f`. The scope of `f` and `setTimeout` are not the same because they are two different functions. Therefore, when we pass `g` to `setTimeout` we are moving `g` out of the scope of `f` into `setTimeout`. – Aadit M Shah Aug 28 '15 at 14:02
  • @ShirgillAnsari Because we are moving `g` out of the scope of `f`, the free variable `i2` becomes an upvalue for `g`. The function `g` must have access to `i2` even though the function `setTimeout` doesn't. The function `setTimeout` may never call `g` (e.g. `setTimeout(g, oneYear)`) but because it now has access to `g` and `g` has access to `i2` therefore the variable `i2` cannot be garbage collected because `setTimeout` might call `g` in the future. Essentially, `i2` should have been garbage collected because the function `f` has finished execution. However, it is not. `g` is closing over it. – Aadit M Shah Aug 28 '15 at 14:10
  • @Aadit: I disagree with the first comment when you said, 'The scope of f and setTimeout are not the same because they are two different functions'. Clearly f is referenced in global scope(window), and setTimeout is a function which is declared within window frame. Hence, there scopes are same. – Farhan stands with Palestine Aug 28 '15 at 14:32
  • @ShirgillAnsari I don't think you understand what a scope of a function is. For example, given `function g() { function f(x) { return x + 1; } function setTimeout(x, y) { return x + y; } }` the scope of `f` is `{ return x + 1; }` and the scope of `setTimeout` is `{ return x + y; }`. They are both defined in the scope of `g` (for global), but that doesn't mean that they are the same scope. They are two different scopes belonging to two different functions. Different functions cannot have the same scope. Period. I hope that helps. This answer has 458 upvotes. Is everyone wrong? I don't think so. – Aadit M Shah Aug 28 '15 at 15:39
  • @Aadit: Agreed now, but I wasn't wrong in my opinion. When you said in the last comment, for the 2 functions f and setTimeout, 'They are both defined in the scope of g (for global)'. I was referring to the referencing scope which is same. i.e (g). For those 458 votes, even before going through the answer, I had already upvoted looking just at the structure of the answer. Thank you once again. 2 functions will always have different scopes even though the scope in which they are referenced might be same. – Farhan stands with Palestine Aug 28 '15 at 16:30
  • Interesting detail but still too hard to follow! My take away so far is this: whenever you have a function inside another one you are using closure and can use it's features. Whether you are returning the enclosed function to pass it around or just execute it whenever the enclosing function is called. I'm hope I'm not too far off the concept... – Saba Ahang Dec 31 '15 at 20:58
  • 1
    This should be nominated for the best stackOverflow answer ever – ChronoFish Feb 15 '19 at 13:01
  • @Peter I could be wrong about this, but I'm pretty sure that for functions that don't use `eval`, modern VMs only keep references to the free variables a function actually closes over, rather than all of the variables on the enclosing scopes, for performance's sake. You can see this in the V8 debugger if you try to mouse over a non-global variable that the current function doesn't close over (the debugger can't get its value) – Andy Mar 13 '19 at 07:13
  • @Andy wow, just catching up on this thread after so many years. :) Yes you must be right. It wouldn't be necssary to keep those references alive when the VM can deduce with certainty that they'd never be used. – Peter Mar 13 '19 at 07:40
98

According to the closure definition:

A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).

You are using closure if you define a function which use a variable which is defined outside of the function. (we call the variable a free variable).
They all use closure(even in the 1st example).

kev
  • 155,172
  • 47
  • 273
  • 272
  • 1
    How does the third version use a variable defined outside the function? – Jon Oct 17 '12 at 09:06
  • 1
    @Jon the returned function use `i2` which is defined outside. – kev Oct 17 '12 at 09:08
  • 1
    @kev You are using closure if you define a function which use a variable which is defined outside of the function......then in "Case 1: Your Friend's Program" of "Aadit M Shah" answer is "function f" a closure ? it uses the i (variable which is defined outside of the function) . does global scope reference a determiner? – internals-in Jul 21 '13 at 15:47
55

In a nutshell Javascript Closures allow a function to access a variable that is declared in a lexical-parent function.

Let's see a more detailed explanation. To understand closures it is important to understand how JavaScript scopes variables.

Scopes

In JavaScript scopes are defined with functions. Every function defines a new scope.

Consider the following example;

function f()
{//begin of scope f
  var foo='hello'; //foo is declared in scope f
  for(var i=0;i<2;i++){//i is declared in scope f
     //the for loop is not a function, therefore we are still in scope f
     var bar = 'Am I accessible?';//bar is declared in scope f
     console.log(foo);
  }
  console.log(i);
  console.log(bar);
}//end of scope f

calling f prints

hello
hello
2
Am I Accessible?

Let's now consider the case we have a function g defined within another function f.

function f()
{//begin of scope f
  function g()
  {//being of scope g
    /*...*/
  }//end of scope g
  /*...*/
}//end of scope f

We will call f the lexical parent of g. As explained before we now have 2 scopes; the scope f and the scope g.

But one scope is "within" the other scope, so is the scope of the child function part of the scope of the parent function? What happens with the variables declared in the scope of the parent function; will I be able to access them from the scope of the child function? That's exactly where closures step in.

Closures

In JavaScript the function g can not only access any variables declared in scope g but also access any variables declared in the scope of the parent function f.

Consider following;

function f()//lexical parent function
{//begin of scope f
  var foo='hello'; //foo declared in scope f
  function g()
  {//being of scope g
    var bar='bla'; //bar declared in scope g
    console.log(foo);
  }//end of scope g
  g();
  console.log(bar);
}//end of scope f

calling f prints

hello
undefined

Let's look at the line console.log(foo);. At this point we are in scope g and we try to access the variable foo that is declared in scope f. But as stated before we can access any variable declared in a lexical parent function which is the case here; g is the lexical parent of f. Therefore hello is printed.
Let's now look at the line console.log(bar);. At this point we are in scope f and we try to access the variable bar that is declared in scope g. bar is not declared in the current scope and the function g is not the parent of f, therefore bar is undefined

Actually we can also access the variables declared in the scope of a lexical "grand parent" function. Therefore if there would be a function h defined within the function g

function f()
{//begin of scope f
  function g()
  {//being of scope g
    function h()
    {//being of scope h
      /*...*/
    }//end of scope h
    /*...*/
  }//end of scope g
  /*...*/
}//end of scope f

then h would be able to access all the variables declared in the scope of function h, g, and f. This is done with closures. In JavaScript closures allows us to access any variable declared in the lexical parent function, in the lexical grand parent function, in the lexical grand-grand parent function, etc. This can be seen as a scope chain; scope of current function -> scope of lexical parent function -> scope of lexical grand parent function -> ... until the last parent function that has no lexical parent.

The window object

Actually the chain doesn't stop at the last parent function. There is one more special scope; the global scope. Every variable not declared in a function is considered to be declared in the global scope. The global scope has two specialities;

  • every variable declared in the global scope is accessible everywhere
  • the variables declared in the global scope correspond to the properties of the window object.

Therefore there are exactly two ways of declaring a variable foo in the global scope; either by not declaring it in a function or by setting the property foo of the window object.

Both attempts uses closures

Now that you have read a more detailed explanation it may now be apparent that both solutions uses closures. But to be sure, let's make a proof.

Let's create a new Programming Language; JavaScript-No-Closure. As the name suggests, JavaScript-No-Closure is identical to JavaScript except it doesn't support Closures.

In other words;

var foo = 'hello';
function f(){console.log(foo)};
f();
//JavaScript-No-Closure prints undefined
//JavaSript prints hello

Alright, let's see what happens with the first solution with JavaScript-No-Closure;

for(var i = 0; i < 10; i++) {
  (function(){
    var i2 = i;
    setTimeout(function(){
        console.log(i2); //i2 is undefined in JavaScript-No-Closure 
    }, 1000)
  })();
}

therefore this will print undefined 10 times in JavaScript-No-Closure.

Hence the first solution uses closure.

Let's look at the second solution;

for(var i = 0; i < 10; i++) {
  setTimeout((function(i2){
    return function() {
        console.log(i2); //i2 is undefined in JavaScript-No-Closure
    }
  })(i), 1000);
}

therefore this will print undefined 10 times in JavaScript-No-Closure.

Both solutions uses closures.

Edit: It is assumed that these 3 code snippets are not defined in the global scope. Otherwise the variables foo and i would be bind to the window object and therefore accessible through the window object in both JavaScript and JavaScript-No-Closure.

brillout
  • 7,804
  • 11
  • 72
  • 84
  • Why should `i` be undefined? You just refer to the parent scope, which is still valid if there were no closures. – leemes Oct 17 '12 at 09:36
  • for the same reason as foo is undefined in JavaScript-No-Closure. i is not undefined in JavaScript thanks to a feature in JavaScript that allows to access variables defined in the lexical parent. This feature is called closure. – brillout Oct 17 '12 at 09:41
  • You didn't understand the difference between referring to already defined variables and *free* variables. In closures, we define free variables which have to be bound in the outer context. In your code, you just *set* `i2` to `i` at the time when you define your function. This makes `i` NOT a free variable. Still, we consider your function a closure, but without any free variable, that's the point. – leemes Oct 17 '12 at 09:48
  • @leemes: I think what brillout.com is trying to explain: what if functions had no other scope than their own (i.e., there is no scope chain). Then `i` would be `undefined` indeed, because it is _not_ available when the outer function is executed (even though it is executed while still in the for-loop). His point: without closures, using higher order functions becomes very limited. – Abel Oct 23 '12 at 20:41
  • @Abel Yeah, I got it; but we could discuss whether we can access `i` because of the feature "closure" or because of how "variable scope" works in JS, which reaches from the current function via literal parent functions until the global scope. Like in C/C++/Java (or similar languages) where we can access the current block, the parent block ... until the function scope, then class scope in OOP languages and finally some global scope. It's just that in JS we don't have blocks, but instead we have functions to scope the variable namespace. – leemes Oct 24 '12 at 14:43
  • 2
    @leemes, I agree. And compared to the accepted answer, this doesn't really show what's actually going on. :) – Abel Oct 24 '12 at 17:39
  • 3
    i think this is the best answer, explaining closures generally and simply and then went into the specific use case. thanks! – tim peterson Mar 18 '13 at 12:49
23

I've never been happy with the way anybody explains this.

The key to understanding closures is to understand what JS would be like without closures.

Without closures, this would throw an error

function outerFunc(){
    var outerVar = 'an outerFunc var';
    return function(){
        alert(outerVar);
    }
}

outerFunc()(); //returns inner function and fires it

Once outerFunc has returned in an imaginary closure-disabled version of JavaScript, the reference to outerVar would be garbage collected and gone leaving nothing there for the inner func to reference.

Closures are essentially the special rules that kick in and make it possible for those vars to exist when an inner function references an outer function's variables. With closures the vars referenced are maintained even after the outer function is done or 'closed' if that helps you remember the point.

Even with closures, the life cycle of local vars in a function with no inner funcs that reference its locals works the same as it would in a closure-less version. When the function is finished, the locals get garbage collected.

Once you have a reference in an inner func to an outer var, however it's like a doorjamb gets put in the way of garbage collection for those referenced vars.

A perhaps more accurate way to look at closures, is that the inner function basically uses the inner scope as its own scope foudnation.

But the context referenced is in fact, persistent, not like a snapshot. Repeatedly firing a returned inner function that keeps incrementing and logging an outer function's local var will keep alerting higher values.

function outerFunc(){
    var incrementMe = 0;
    return function(){ incrementMe++; console.log(incrementMe); }
}
var inc = outerFunc();
inc(); //logs 1
inc(); //logs 2
Erik Reppen
  • 4,605
  • 1
  • 22
  • 26
  • You are right about the 'snapshot' (I think, you refer to my answer) by that. I was looking for a word that would indicate the behavior. In your example, it can be seen as a 'hotlink' closure construction. When catching the closure as parameter in the inner-function, one could state it behaves as a 'snapshot'. But I agree, misused words only adds confusion to the subject. If you have any suggestions about that, I will update my answer. – Andries Oct 25 '12 at 15:15
  • It might help in explanation if you give the inner function were a named function. – Phillip Senn Mar 18 '13 at 16:19
  • Without closures, you would get an error because you are trying to use a variable that doesn't exist. – Ruan Mendes Jul 01 '15 at 17:47
  • Hmm... good point. Did referencing an undefined var ever not throw an error since it would ultimately look up as a property on the global object or am I confusing with assignment to undefined vars? – Erik Reppen Jul 06 '15 at 15:29
17

You are both using closures.

I 'm going with the Wikipedia definition here:

In computer science, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables) of that function. A closure—unlike a plain function pointer—allows a function to access those non-local variables even when invoked outside of its immediate lexical scope.

Your friend's attempt clearly uses the variable i, which is non-local, by taking its value and making a copy to store into the local i2.

Your own attempt passes i (which at the call site is in scope) to an anonymous function as an argument. This is not a closure so far, but then that function returns another function that references the same i2. Since inside the inner anonymous function i2 is not a local, this creates a closure.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • Yeah, but I think the point is *how* he is doing it. He just copies `i` to `i2`, then defines some logic and executes this function. If I would not *execute* it immediately, but store it in a var, and executed it after the loop, it would print 10, wouldn't it? So it did *not* capture i. – leemes Oct 17 '12 at 09:11
  • 6
    @leemes: It captured `i` just fine. The behavior you are describing is not a result of closure vs non-closure; it's a result of the closed-over variable being changed in the meantime. You are doing the same thing using different syntax by immediately calling a function and passing `i` as an argument (which copies its current value on the spot). If you put your own `setTimeout` inside another `setTimeout` the same thing will happen. – Jon Oct 17 '12 at 09:16
13

You and your friend both use closures:

A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.

MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures

In your friend's code function function(){ console.log(i2); } defined inside closure of anonymous function function(){ var i2 = i; ... and can read/write local variable i2.

In your code function function(){ console.log(i2); } defined inside closure of function function(i2){ return ... and can read/write local valuable i2 (declared in this case as a parameter).

In both cases function function(){ console.log(i2); } then passed into setTimeout.

Another equivalent (but with less memory utilization) is:

function fGenerator(i2){
    return function(){
        console.log(i2);
    }
}
for(var i = 0; i < 10; i++) {
    setTimeout(fGenerator(i), 1000);
}
Community
  • 1
  • 1
Andrew D.
  • 8,130
  • 3
  • 21
  • 23
  • 1
    I don't see why your solution vs my friend's solution "is more faster and with less memory utilization", could you elaborate? – brillout Oct 17 '12 at 09:07
  • 3
    In you solution you create 20 function objects (2 objects on each loop: 2x10=20). Same result in solution of your frend. In "my" solution only 11 function objects is created: 1 before for loop and 10 "inside" - 1+1x10=11. As result - less memory usage and increase of speed. – Andrew D. Oct 17 '12 at 09:11
  • 1
    In theory, that would be true. In practice, also: See this JSPerf benchmark: http://jsperf.com/closure-vs-name-function-in-a-loop/2 – Rob W Oct 17 '12 at 09:20
11

Closure

A closure is not a function, and not an expression. It must be seen as a kind of 'snapshot' from the used variables outside the function scope and used inside the function. Grammatically, one should say: 'take the closure of the variables'.

Again, in other words: A closure is a copy of the relevant context of variables on which the function depends on.

Once more (naïf): A closure is having access to variables who are not being passed as parameter.

Bear in mind that these functional concepts strongly depend upon the programming language / environment you use. In JavaScript, the closure depends on lexical scoping (which is true in most C-languages).

So, returning a function is mostly returning an anonymous/unnamed function. When the function access variables, not passed as parameter, and within its (lexical) scope, a closure has been taken.

So, concerning your examples:

// 1
for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i); // closure, only when loop finishes within 1000 ms,
    }, 1000);           // i = 10 for all functions
}
// 2
for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i; // closure of i (lexical scope: for-loop)
        setTimeout(function(){
            console.log(i2); // closure of i2 (lexical scope:outer function)
        }, 1000)
    })();
}
// 3
for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2); // closure of i2 (outer scope)

        }
    })(i), 1000); // param access i (no closure)
}

All are using closures. Don't confuse the point of execution with closures. If the 'snapshot' of the closures is taken at the wrong moment, the values may be unexpected but certainly a closure is taken!

Fabian Lauer
  • 8,891
  • 4
  • 26
  • 35
Andries
  • 1,547
  • 10
  • 29
10

Let's look at both ways:

(function(){
    var i2 = i;
    setTimeout(function(){
        console.log(i2);
    }, 1000)
})();

Declares and immediately executes an anonymous function that runs setTimeout() within its own context. The current value of i is preserved by making a copy into i2 first; it works because of the immediate execution.

setTimeout((function(i2){
    return function() {
        console.log(i2);
    }
})(i), 1000);

Declares an execution context for the inner function whereby the current value of i is preserved into i2; this approach also uses immediate execution to preserve the value.

Important

It should be mentioned that the run semantics are NOT the same between both approaches; your inner function gets passed to setTimeout() whereas his inner function calls setTimeout() itself.

Wrapping both codes inside another setTimeout() doesn't prove that only the second approach uses closures, there's just not the same thing to begin with.

Conclusion

Both methods use closures, so it comes down to personal taste; the second approach is easier to "move" around or generalize.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • I think the difference is: His solution (1st) is capturing by reference, mine (2nd) is capturing by value. In this case it doesn't make a difference, but if I were to put the execution in another setTimeout, we would see that his solution has the problem that it then uses the final value of i, not the current, while mine sill uses the current value (since captured by value). – leemes Oct 17 '12 at 09:30
  • @leemes You both capture in the same way; passing a variable via function argument or assignment is the same thing ... could you add to your question how you would wrap the execution in another `setTimeout()`? – Ja͢ck Oct 17 '12 at 09:35
  • let me check this out... I wanted to show that the function object can be passed around and the original variable `i` can be changed without affecting what the function whould print, not depending on where or when we execute it. – leemes Oct 17 '12 at 09:40
  • Wait, you did not pass a function to (the outer) setTimeout. Remove those `()`, thus passing a function, and you see 10 times the output `10`. – leemes Oct 17 '12 at 09:43
  • @leemes As mentioned before, the `()` is exactly what makes his code work, just like your `(i)`; you didn't just wrap his code, you made changes to it .. therefore you can't make a valid comparison anymore. – Ja͢ck Oct 17 '12 at 09:46
  • Hmm. I pass `i`, but I return a function. So I passed a function to `setTimeout` (which expects one). You too executed the function, not returning anything but already executing the final code. Thus you do not pass anything to `setTimeout`, thus giving me an error in my JS console. Note that your code should have a delay of 2 seconds, but it has a delay of 1. Because the outer timeout is useless. (This is the error message in my console, actually a warning.) – leemes Oct 17 '12 at 09:50
  • @leemes Hmm right, his code would pass `undefined` to the first argument of `setTimeout()`; that said, the run semantics are not identical between both approaches anyway, which is why you see different behaviour. – Ja͢ck Oct 17 '12 at 09:55
  • and because mine was captured / bound by value and he binds by reference, we only see a difference if we store and execute the resulting closure *after* the loop. This can be done using setTimeout, but could also be done by storing it in an array of functions and executing them afterwards. *This* is why I thought his solution is no closure, but in fact it is; but simply *a different one* than mine, without *captured* variables. – leemes Oct 17 '12 at 10:03
9

I wrote this a while ago to remind myself of what a closure is and how it works in JS.

A closure is a function that, when called, uses the scope in which it was declared, not the scope in which it was called. In javaScript, all functions behave like this. Variable values in a scope persist as long as there is a function that still points to them. The exception to the rule is 'this', which refers to the object that the function is inside when it is called.

var z = 1;
function x(){
    var z = 2; 
    y(function(){
      alert(z);
    });
}
function y(f){
    var z = 3;
    f();
}
x(); //alerts '2' 
Nat Darke
  • 871
  • 7
  • 3
6

After inspecting closely, looks like both of you are using closure.

In your friends case, i is accessed inside anonymous function 1 and i2 is accessed in anonymous function 2 where the console.log is present.

In your case you are accessing i2 inside anonymous function where console.log is present. Add a debugger; statement before console.log and in chrome developer tools under "Scope variables" it will tell under what scope the variable is.

Ramesh
  • 13,043
  • 3
  • 52
  • 88
  • 2
    The "Closure" section at the right panel is used because there's no more specific name. "Local" is a stronger indication than "Closure". – Rob W Oct 17 '12 at 09:05
4

Consider the following. This creates and recreates a function f that closes on i, but different ones!:

i=100;

f=function(i){return function(){return ++i}}(0);
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));

f=function(i){return new Function('return ++i')}(0);        /*  function declarations ~= expressions! */
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));

while the following closes on "a" function "itself"
( themselves! the snippet after this uses a single referent f )

for(var i = 0; i < 10; i++) {
    setTimeout( new Function('console.log('+i+')'),  1000 );
}

or to be more explicit:

for(var i = 0; i < 10; i++) {
    console.log(    f = new Function( 'console.log('+i+')' )    );
    setTimeout( f,  1000 );
}

NB. the last definition of f is function(){ console.log(9) } before 0 is printed.

Caveat! The closure concept can be a coercive distraction from the essence of elementary programming:

for(var i = 0; i < 10; i++) {     setTimeout( 'console.log('+i+')',  1000 );      }

x-refs.:
How do JavaScript closures work?
Javascript Closures Explanation
Does a (JS) Closure Require a Function Inside a Function
How to understand closures in Javascript?
Javascript local and global variable confusion

Community
  • 1
  • 1
ekim
  • 41
  • 2
  • snippets tried for 1st time - not sure how to control - `Run' only was desired - not sure how to remove the `Copy` – ekim Mar 15 '15 at 14:03
-1

I would like to share my example and an explanation about closures. I made a python example, and two figures to demonstrate stack states.

def maker(a, b, n):
    margin_top = 2
    padding = 4
    def message(msg):
        print('\n’ * margin_top, a * n, 
            ' ‘ * padding, msg, ' ‘ * padding, b * n)
    return message

f = maker('*', '#', 5)
g = maker('', '♥’, 3)
…
f('hello')
g(‘good bye!')

The output of this code would be as follows:

*****      hello      #####

      good bye!    ♥♥♥

Here are two figures to show stacks and the closure attached to the function object.

when the function is returned from maker

when the function is called later

When the function is called through a parameter or a nonlocal variable, the code needs local variable bindings such as margin_top, padding as well as a, b, n. In order to ensure the function code to work, the stack frame of the maker function which was gone away long ago should be accessible, which is backed up in the closure we can find along with the function message object.

  • I would like to remove this answer. I realized that the question is not about what is closure, so I would like to move it to the other question. – Eunjung Lee May 12 '18 at 04:18
  • 2
    I believe you have the ability to delete your own content. Click the `delete` link under the answer. – Rory McCrossan Jun 11 '19 at 10:11