Summary
The let
and const
block bindings introduce lexical scoping to JavaScript. These declarations are not hoisted and only exist within the block in which they are declared. This offers behavior that is more like other languages and less likely to cause unintentional errors, as variables can now be declared exactly where they are needed. As a side effect, you cannot access variables before they are declared, even with safe operators such as typeof
. Attempting to access a block binding before its declaration results in an error due to the binding’s presence in the temporal dead zone (TDZ).
In many cases, let
and const
behave in a manner similar to var
; however, this is not true for loops. For both let
and const
, for-in
and for-of
loops create a new binding with each iteration through the loop. That means functions created inside the loop body can access the loop bindings values as they are during the current iteration, rather than as they were after the loop’s final iteration (the behavior with var
). The same is true for let
declarations in for
loops, while attempting to use const
declarations in a for
loop may result in an error.
The current best practice for block bindings is to use const
by default and only use let
when you know a variable’s value needs to change. This ensures a basic level of immutability in code that can help prevent certain types of errors.