This is part 2 of a 10-part series of articles introducting you to some of the features of the upcoming ES6 specification. It may be helpful to read the first part if you missed it.
In ES5 (the current major revision of the ECMAScript specification, available in
all modern environments) variables can only be scoped to the variable
environment of an execution context. In practice, this means variables (declared
var statement) are accessible throughout the execution context in which
In ES6 variable and function declarations continue to behave in this manner
(which is a good thing for backwards compatability). However, the introduction
let keyword gives us some more flexibility:
Variables declared with a
let statement are created as bindings on the
lexical environment, rather than the variable environment, of the current
execution context. A change to the specification of block statements in ES6
means that each block has its own lexical environment. In the above example, a
new lexical environment is created when the block (the body of the
statement) is evaluated. When the
let statement is evaluated a binding is
added to this lexical environment and is innaccessible from the outer lexical
environment (that of the function declaration itself).
We can see how new lexical environments for blocks are created in detail in the ES6 draft specification (ES6 §13.1.2):
- Let oldEnv be the running execution context’s LexicalEnvironment.
- Let blockEnv be the result of calling NewDeclarativeEnvironment passing oldEnv as the argument.
- Perform Block Declaration Instantiation using StatementList and blockEnv.
- Set the running execution context’s LexicalEnvironment to blockEnv.
It’s worth noting that
let declarations are not hoisted in the same way as
var declarations. Attempting to reference an identifier created as part of a
let declaration before the declaration itself has been evaluated will result
in an error:
You can use
let declarations anywhere you can use a
var declaration. Of
particular interest is the usage in loop initialisers. When using a
statement as a loop initialiser the declaration will be hoisted as discussed
above and the variable will be accessible throughout the execution context in
which it appears. This can be a common cause of confusion for beginners,
especially those coming from a language that does implement block scoping. With
the addition of the
let declaration we can ensure our loop counter is only
accessible within its block:
ES6 introduces another type of declaration,
const (ES6 §
13.2.1). It has the same block scoped binding semantics as
but its value is a read-only constant. They must have an initialiser, unlike
Note that the
const keyword has been supported by numerous engines for some
time now, but with slightly different semantics to the ES6 spec. One of the main
differences is that constants are currently declared in function scope, rather
than block scope. Attempting to assign a new value to a constant fails, but does
not produce an error in all engines.
Function Declarations in Blocks
In ES5 function declarations were not allowed to appear in blocks. Various implementations allowed this anyway, leading to code that behaves differently across those implementations (ES5 §12):
Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations.
ES6 proposes to explictly allow the use of function declarations within blocks,
again following much the same semantics as
However, there does appear to have been some debate around whether or not it will be possible to implement this so I’m unclear as to whether this will make it into the final spec or not. If you’re interested in discussions around these difficulties the Mozilla and WebKit issues are good places to look.
Come back soon for the next part, where we’ll have a look at destructuring, probably one of the most talked-about ES6 features. Follow us on twitter to be notified when it’s posted, and don’t forget we’re hiring…