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?

4
  • Related? What Are Functions/Closures/Lambdas, From A Data Structures Perspective? Commented Jan 25, 2016 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. Commented Jan 25, 2016 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 youtube.com/watch?v=oWSQ4mWNFPU Commented Jan 25, 2016 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. Commented Jan 25, 2016 at 19:35

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

So if you have a closure referencing only one local variable, are all local variables held?
@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, because it is not possible to generally determine if a given var is never-again accessible in the future.
@AndrewWilliamson That used to be the case, but in Chrome, only the used variables are stored in the closure. If you add an eval to your code, Chrome keeps all the variables so you can access them.
That makes sense. My example was kind of going along those lines, but it seems I have forgotten how to JavaScript.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.