From the previous article, we know that a variable is a property of the LexicalEnvironment object.
Here we discuss access to outer variables and nested functions. In-depth understanding of closures follows automatically.
Access to outer variables
What if a variable is accessed, but it isn’t local? Like here:
In this case, the the interpreter finds the variable in the outer LexicalEnvironment object.
The process consists of two steps:
- First, when a function
f is created, it is not created in an empty space.
There is a current LexicalEnvironment object. In the case above, it’s window (a is undefined at the time of function creation).

When a function is created, it gets a hidden property, named [[Scope]], which references currentLexicalEnvironment.

- Later, when the function runs, it creates it’s own
LexicalEnvironment and links it with [[Scope]].
So when a variable is not found in the local LexicalEnvironment, it is searched outside:

If a variable is read, but can not be found anywhere, the error is generated.
Certain language constructs block the error, for example typeof x works if there is no x (and returnsundefined), but that’s an exception.
If a variable is set, but not found anywhere, then it is created in the outmost LexicalEnvironment, which iswindow.
Nested functions
Functions can be nested one inside another, forming a chain of LexicalEnvironments which can also be called a scope chain.
LexicalEnvironments form a chain (from inside out):
So, function
g has access to
g, a and
f.
Closures
Nested function may continue to live after the outer function has finished:
3 |
this.say = function(phrase) { |
4 |
alert(name + ' says: ' + phrase) |
9 |
var user = new User('John') |
Marking up LexicalEnvironments:

Note, the this context is not related to scopes and variables. It does not participate here.
As we see, this.say is a property in the user object, so it continues to live after User completed.
And if you remember, when this.say is created, it (as every function) gets an internal referencethis.say.[[Scope]] to current LexicalEnvironment. So, the LexicalEnvironment of the current Userexecution stays in memory. All variables of User also are it’s properties, so they are also carefully kept, not junked as usually.
The whole point is to ensure that if the inner function wants to access an outer variable in the future, it is able to do so.
- The inner function keeps a reference to the outer
LexicalEnvironment.
- The inner function may access variables from it any time even if the outer function is finished.
- The browser keeps the
LexicalEnvironment and all it’s properties(variables) in memory until there is an inner function which references it.
This is called a closure.
Mutability of LexicalEnvironment
Several function may share same outer LexicalEnvironment. In this case they can modify it’s properties.
In the example below, this.fixName changes name, which is used by this.say:
03 |
this.fixName = function() { |
04 |
name = 'Mr.' + name.toUpperCase() |
07 |
this.say = function(phrase) { |
08 |
alert(name + ' says: ' + phrase) |
13 |
var user = new User('John') |
17 |
user.say("I'm alive!") |
Here user.fixName.[[Scope]] and user.say.[[Scope]] reference same LexicalEnvironment, which corresponds to new User run.
From (1) to (2), the LexicalEnvironment.name is updated, so both functions see the variable change.
Variables in outer LexicalEnvironment may change.
Inner functions always see the last value.
The notorious closure loop
The task below contains interesting tricks, best demonstrated by an example. Please, glance at the solution, or, much better, try to solve it.
Note that the shooter function. Does not have a variable named i.
So, when it is called, the interpreter takes i from the outer LexicalEnvironment.
The problem is that at the time when shooters are run, function makeArmy has already finished the execution.
The loop has finished and the variable i is now 10.
There are two possible solutions.
The first one is to put the correct value into the shooting function itself.
05 |
for(var i=0; i<10; i++) { |
07 |
var shooter = function() { |
08 |
alert( arguments.callee.i ) |
12 |
shooters.push(shooter) |
Another, more advanced solution is to use an extra function to trap the current value of i:
05 |
for(var i=0; i<10; i++) { |
07 |
var shooter = function(i) { |
15 |
shooters.push(shooter) |
Let’s consider the highlighted fragment more thoroughly.
1 |
var shooter = function(i) { |
Here, the actual shooting function is created as the result of an anonymous function(i)which is created and executed in one place.
So, when it comes to executing alert(i), it will be taken from LexicalEnvironment of the anonymous function.
So, the anonymous function traps current i into it’s LexicalEnvironment and allows the shooter to access it.
The last way is to wrap the whole loop into temporary function. Sometimes that’s more readable:
05 |
for(var i=0; i<10; i++) (function(i) { |
07 |
var shooter = function() { |
11 |
shooters.push(shooter) |
The (function(i) { ... }) definition is wrapped into brackets to make sure the interpreter treats that as expression.
[[Scope]] for new Function
There is an exception to general scope binding rule. When you create a function using new Function, it’s[[Scope]] points to window, not to current LexicalEnvironment.
The following example demonstrates how a function, created with new Function ignores local variable aand outputs the global variable.
The regular behavior:
05 |
var func = function() { alert(a) } |
And now the function, created by new Function:
5 |
var func = new Function('', 'alert(a)') |
http://javascript.info/tutorial/closures
Summary
We discussed the following topics:
- How variables are handled in JavaScript.
- How scopes work.
- What is a closure and how to use it.
- Possible pitfalls and subtles in working with closures.
Closures in JavaScript is like a salt. You can live without it, but not very long. Usually people put it everywhere…