ES6 - The let keyword


ES6 - The let keyword and block scope:

In traditional JavaScript, we have global scope and function scope, and variable 
declarations are hoisted to the top.  ES6 offers us the let keyword, and it let
us accomplish block-level scope.  Consider:

function() {
  var baz = 4;
  if (x) {
    let y = 2;

In the above code, inside the if block, the variable y only have the value of 2.  
Whatever we do to y inside this block stay local to this block.  If there is 
another variable y outside of this block, that variable is not impacted.

Variables declared with let are also hoisted, but they are hoisted to the top of the 
block.  See the above links for more details.

In most C-based languages, variables (also known as bindings) are bound to a 
value inside a scope, are created at the spot where the declaration occurs.  In 
JavaScript, this is not the case.  Where our variables are actually created 
depends on how we declare them.  Variables declarations using the var keyword 
are treated as if they are declared at the top of the function (or in the global 
scope, if declared outside of a function) regardless of where the actual 
declaration occurs.  This is called hoisting.  Consider the following function:

function getValue(condition) {
  if (condition) {
    var x = "blue";
    return value;
  } else {
    // The variable x exists here with a value of undefined
    return null;
  // The variable x exists here with a value of undefined.

If we are unfamiliar with JavaScript, we might expect the variable x to be 
created only if condition evaluates to true.  However, the variable x is created 
regardless.  Behind the scene, the JavaScript engine changes the getValue 
function to look like:

function getValue(condition) {
  var x;
  if (condition) {
    x = "blue";
    return x;
  } else {
    return null;

The declaration of the variable is hoisted to the top, and the initialization 
remains in the same spot.  That means that the variable x is still accessible 
from within the else block.  If accessed from the else block, the variable x 
would just have the value of undefined because it has not been initialized.

ECMAScript 6 introduce block-level scoping.  Block-level declarations declare 
bindings that are inaccessible outside a given block scope.  Block scopes, also 
called lexical scopes, are created in the following places:

1. Inside a function
2. Inside a block (indicated by the { and } characters)

Block scoping is how many C-based language work, and the introduction of block-
level declarations in ECMAScript 6 is intended to provide the same flexibility 
and uniformity to JavaScript.

The let declarations are not hoisted to the top of the enclosing block.

If an identifier has already been defined in a scope, using the identifier in 
a let declaration in that scope causes an error.  For example:

var count = 30;
let count = 40; // Throws an error.

In the above code, the variable count is declared twice, once with the var 
keyword and once with the let keyword.  Because the let keyword will not 
redefine an identifier that already exists in the same scope, the let 
declaration will throw an error.  Conversely, no error is thrown if a let 
declaration creates a new variable with the same name as a variable in its 
containing scope as demonstrated in the following code:

var count = 30;
if (condition) {
  let count = 40; // does not thrown an error

In the above code, the let declaration does not throw an error because it 
creates a new variable, also named as count within the if block instead of 
creating count in the surrounding block.  Inside the if block, this new variable 
hides the count variable from the surrouding block, preventing access to it 
until execution exits the if block.

Block Bindings in Loops.  Perhaps one area where developers most want block-
level scoping of variables is within for loops, where the throw-away counter 
variable is meant to be used only inside the loop.  For example, it is not 
uncommon to see:

for (var i = 0; i < 10; i++) {

After the above code, the variable i is still accessible.  In other languages 
where block-level scoping is the default, the above code should work as intended 
(only the for loop should have access to the variable i, and after the for loop, 
the variable i should not be accessible).  However, in JavaScript, the variable 
i is still accessible after the loop is completed because the var declaration is 
hoisted.  Using let should produce the intended behavior:

for (let i = 0; i < 10; i++) {

console.log(i); // is is not accessible here, and will throw error.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License