0

I've seen a really cool explanation of closure. So in my view closure is a way to store data somewhere. Let's see examples of closure and example without closure:

Without closure:

function F1(x,y)
{
  var z=5;
  function F2(){
     console.log('x='+x+'y='+y+'z='+z);
  }
  F2();
}

F1(1,2)

With closure:

function F1(x,y)
{
  var z=5;
  function F2(){
     console.log('x='+x+'y='+y+'z='+z);
  }
  return F2();
}

var p=F1(1,2)
p();

I've understood that in closure when F1() finishes its work, then F1() clears connection to the store where values of F1 are kept. But F2() still keeps the reference to the store of values.

Let's see images:

Without closure: enter image description here

With closure: enter image description here

I would like to know what happens in memory. I have little knowledge of C# and that reference types are reason to create objects in heap for each reference type. My question is how is it possible to store values of F2() if values of F1() are already garbage collected?

I mean what happens in memory - how many are objects created?(JavaScript creates objects on the heap like C#?) or maybe JavaScript just uses stack to store values of functions?

StepUp
  • 36,391
  • 15
  • 88
  • 148
  • Related? [What Are Functions/Closures/Lambdas, From A Data Structures Perspective?](http://stackoverflow.com/q/26102127/710446) – apsillers Jan 25 '16 at 19:18
  • "*how is it possible to store values of F2() if values of F1() are already garbage collected?*" -- it's not; F1's variables are *not* garbage collected if F2 can access them (and F2 is still accessible). Your illustration isn't very representative; maybe you should have F1 be a balloon inside of an F2 balloon held by the execdution environment. As long as the F2 variable scope is accessible, F1's scope must be preserved as well. – apsillers Jan 25 '16 at 19:23
  • @apsillers no, as there is no information about garbage collection and memory allocation. These images are taken from a really cool video tutorial https://www.youtube.com/watch?v=oWSQ4mWNFPU – StepUp Jan 25 '16 at 19:25
  • 1
    That answer deals extensively with the creation of EnvironmentRecords and LexicalEnvironments, which are the data structures that exist in memory that make closures possible. I agree, though, that the answer doesn't address how EnvironmentRecords are garbage collected. – apsillers Jan 25 '16 at 19:35

1 Answers1

3

Every time you call a function, a new activation context containing the local variables is created. If inner functions use any of those variables, the activation context is saved (in a closure) so the local variables can be accessed outside of that function.

There is only one closure created per activation context (function call). That is,

// One closure is created every time you call doSomething
// The loop in doSomething creates a single closure that is shared 
// by all the divs handlers (or all the handlers point to the same function
// instance and its closure)
function doSomething(divs) {
   for (var i =0; i < divs.length; i++) {
     div.onclick = function() {
       // Because there is only one closure, i will be the same
       // for all divs
       console.log('Clicked div, i is'  + i);
     }
   }
}

// One closure here
doSomething([div1,div2,div3]);
// One closure here
doSomething([div9,div10, div11]);

The garbage collector will never garbage collect a closure that still has references to it. As an aside, this was one of the sources for memory leaks. There's often a circular reference between a closure and a DOM element, which kept IE from garbage collecting that closure because it couldn't detect that circular reference between DOM elements and regular JavaScript objects.

Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • So if you have a closure referencing only one local variable, are all local variables held? – Andrew Williamson Jan 25 '16 at 19:40
  • 2
    @AndrewWilliamson According to the spec, they are *conceptually* held, but if there is no way to access them ever again, the environment can garbage safely collect the unused variables, since there's no observable difference between CGing them and not CGing them. (Eliminating extant-but-inaccessible things is what CGing *is*.) Note that [if an inner function has a direct `eval` call, then all outer variables must be actually maintained in memory](http://stackoverflow.com/a/34724078), because it is not possible to generally determine if a given var is never-again accessible in the future. – apsillers Jan 25 '16 at 19:41
  • @AndrewWilliamson That used to be the case, [but in Chrome, only the used variables are stored in the closure](http://stackoverflow.com/a/14987697/227299). If you add an `eval` to your code, Chrome keeps all the variables so you can access them. – Ruan Mendes Jan 25 '16 at 19:48
  • That makes sense. My example was kind of going along those lines, but it seems I have forgotten how to JavaScript. – Andrew Williamson Jan 25 '16 at 19:51