Console Learner — An interactive JavaScript course.


3.4 Scopes & Closures

Declaring variables inside a function used to be the only way to avoid creating global variables. It has therefore been very common to wrap code in an anonymous function to control global namespace export.

Since let and const was introduced (in ES6), it is now also possible to bind variables to a statement block.

The image below shows the scopes used in this example:

Variable scopes

JavaScript unfortunately lacks a mechanism with which to introspect name bindings in a scope (except for the global scope).

The possibilities and implications of function closures are sometimes hard to understand, but we'll revisit the topic later. In particular this has repercussions on memory usage, as a reachable scope (and its bindings) cannot be reclaimed.
>>>
var a = 1;


  
>>>
function test() {
    var a = 2;
    return a;
}


  
>>>
test()
2
As expected, the local variable in the function shadows the global variable value.
>>>
a
1
The global value remains unmodified and is the only one accessible from the global scope (where this console runs).
>>>
function inc() {
    return b++;
}

  
A function can reference names in the parent scope. Even if a name does not yet exist.
>>>
inc()
ReferenceError: Can't find variable: b
The error happens in run-time, if the name cannot be found.
>>>
var b = 13;


  
>>>
inc()
13
By retroactively creating the missing variable, we can make the function work correctly. This shows that the name is looked up at run-time on each call.
>>>

The console allows you to interact with the course material and examples. Use the following keys:

A special logging function is also available:


Need more magic? Check out the other developer tools on this site.