Daniel Jour
Daniel Jour

Reputation: 16156

Over how much of its enclosing scope does a (javascript) closure close?

When I have some function that uses variables from its enclosing scope(s) and use that function outside of this scope (these scopes), then this is called a closure.

Is there any specification about over "how much" of its enclosing scope(s) a function has to close? (Or, put differently, over "how less" it absolutely needs to close?)

Consider:

function Outer() {
  var bigGuy = createSomethingHuge();
  var tinyNumber = 42;
  return (function () { /* CONTENTS */ });
}

Or even:

function Layer1() {
  var bigOne = somethingHugePlease();
  var Layer2 = function() {
    var bigToo = morePlease();
    var Layer3 = function() {
       var huge = reallyHuge();
       var tiny = 42;
       return (function () { /* CONTENTS */ });
    };
    return Layer3();
  };
  return Layer2();
}

Which of these variables does the final returned function close over? Does it depend on the contents of that final function (eval ...?)?

I'm mostly interested into whether there is some kind of specification for these cases, not so much about the behavior of some specific implementation.

Upvotes: 2

Views: 296

Answers (2)

Bergi
Bergi

Reputation: 664971

I'm mostly interested into whether there is some kind of specification for these cases

The ECMAScript specification does not really detail this. It simply says that a function closes over the whole lexical environment which includes all variables in all parent scopes, organised in so-called environment records.

Yet it does not specify how an implementation should do garbage-collection - so engines do have to optimise their closures themselves - and they typically do, when they can deduce that some "closed over" variable is never needed (referenced). Specifically, if you do use eval anywhere in the closure, they cannot do that of course, and have to retain everything.

not so much about the behavior of some specific implementation

Regardless, you'll want to have a look at How JavaScript closures are garbage collected, garbage collection with node.js, About closure, LexicalEnvironment and GC and How are closures and scopes represented at run time in JavaScript

Upvotes: 2

traktor
traktor

Reputation: 19354

The scope chain of a nested function contains references to activation objects of all outer functions whose execution resulted in definition of the nested function. These activation objects store ALL values in place when the outer function call returned and continue to exist because they are in a scope chain.

So a closure, by definition, captures ALL variable values in scope. eval("typeof bigGuy"); within 'function () { /* CONTENTS */ } should demonstrate this.

The ECMA standards probably* cover this (if you are writing a javascript engine and have the time). A solution may be to set large sized variables to undefined when their value is no longer required.


*Based on reading ECMA 3.61 ten years ago. The computer science term "closure" did not appear in the standard. The production of closures has to be deduced by the reader as an implicit consequence of how nested function scope chains are constructed - which is in the standard. Scope chains comprise the currently executing function's activation object, outer functions' activation objects in reverse order, followed by the global object. The scope chain cannot be modified in user code.

Upvotes: 0

Related Questions