Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do closures in Javascript get a reference to the full outer function or do they only get references to the variables they actually use?

Just out of curiosity, do closures in JavaScript get a reference to the whole "outer environment", or is the returned function analyzed to see which variables in the outer scope it references and then only gets references to those?

like image 442
Sam Avatar asked Feb 09 '11 15:02

Sam


2 Answers

Theoretically, a nested function in JavaScript has access to all variables in all containing scopes. When an identifier is encountered, it is resolved against the scope chain, which is a list that includes objects whose properties are variables and function parameters of each containing execution context (i.e. enclosing function), innermost first, plus the global object at the end. A function object drags its scope chain around with it wherever it goes.

However, these Variable objects and the scope chain are only specification constructs and are not accessible directly, so implementations are free to make whatever optimizations they like, including analyzing function code and only exposing variables that are accessed by a function and any functions nested within it, so long as the specification always appears to be satisfied. However, it's best to assume that if you have an enormous object that is accessible via a closure to a function, that enormous object is going to stick around at least until that function is garbage collected.

If you want further information about this, read the ECMAScript specification. A good starting point would be section 10.1.4: http://bclary.com/2004/11/07/#a-10.1.4. This is not the current version of the specification but is the baseline for what all current major browsers implement.

like image 182
Tim Down Avatar answered Oct 07 '22 15:10

Tim Down


The answer is "yes and no". When a function "leaks" out of a function activation, the entire context is preserved*. However, as there's no way to refer to the context itself, the code of a function cannot "investigate" the context(s). Thus:

function leaker() {
  var i = 100, j = "hello there";
  return function() {
    i = i - 1;
    return i == 0;
  }
}

The returned function can only ever refer to "i". The variable "j" may stick around, but there's no way for code in that returned function to "find" it.

* I write that the context is preserved, which I believe to be true, but technically that's the business of the interpreter/runtime.

like image 23
Pointy Avatar answered Oct 07 '22 15:10

Pointy