ES6: ‘let’ keyword to declare variable in JavaScript

In Short – “LET keyword allows us to declare a variable with the block-level scope which was not possible in JavaScript programming language before.”

Till EcmaScript 5 one of the tricky parts in JavaScript has been the way variable declaration works. In most of the traditional, c or OOPS based languages, variable scope is defined according to the declaration but it was not the case till EcmaScript 5.

Traditionally, variables were declared using keyword ‘var’ and it has only two level of scoping i.e. either the variables have the global scope or the functional scope and due to ‘hoisting’ we can use a variable even before it is declared. EcmaScript 6 now has provided a way to create variables with the scope as block level and it now behaves much similar to the way we have seen in almost every other traditional language.


What happens till ES 5 –

Till now there was only one way to declare a variable and it is using keyword ‘var’. Variables declared using ‘var’ inside the function are hoisted at the top of the function (or to global scope if declared outside the function) regardless of where the actual declaration occurs. In hoisting variable declaration moves to the top of the functional or global scope. So, even if we try to use these variables before where we actually declare or initialize them, we will never get the ‘ReferenceError’. Even if we declare a variable inside any loop or if condition block or whatever, it will always be available outside of that block. For eg –

var getValue = function (condition) {
    
    if (condition) {
        var value = "Codingeek";
        return value;
    }
    else {
        return value;
    }
}
var value1 = getValue(true);
var value2 = getValue(false);

console.log(value1); // Value returned is "Codingeek".
console.log(value2); // Value returned is "undefined".

In the above JavaScript code example, variable value is accessible outside ‘if block’ also because behind the scene JavaScript engine changes the implementation to look like this –

var getValue = function (condition) {

    // Variables declared using 'var' are hoisted at
    // the top i.e. declaration moves as the first statement of function
    var value;
    if (condition) {
        value = "Codingeek";
        return value;
    }
    else {
        return value;
    }
}

Let Declaration –

Now in ES6 using the let keyword enables you to define variables with enclosing block. The scope of variables declared by ‘let’ is the block in which it is defined as well as the sub-blocks, condition being that it is declared before it is used. For example, if we use ‘let’ keyword in above function and try to access it outside the block it will show ‘ReferenceError’ on execution.

var getValue = function (condition) {
 if (condition) {
     let value = "Codingeek";
        return value;
    }
    else {
        return value;
   }
}
var value1 = getValue(true);
var value2 = getValue(false);

console.log(value1); // Value returned is "Codingeek".
console.log(value2); // ReferenceError: value is not defined is shown.

Temporal Dead Zone –

  1. On re-declaring variable with the same name in the same scope. Although we can declare a variable with the same name in the enclosing scope. For eg –
    var differentScope;
    if (x) {
        var foo1;
        let foo2;
    
        let differentScope; // This will work as scope of variables is different
    
        // All statements below will give TypeError
        let foo1;
        let foo2;
        var foo2;
    }
    
  2. Using the variable even before the declaration code is executed. For Ex-
    if (x) {
        console.log(typeof foo);  // ReferenceError thrown.
        let foo;
    }
    

Exampe/Use Case of ‘let’ keyword-

let can also be used to avoid problems with closures. It binds fresh value rather than keeping an old reference as shown in examples below.

var nodes = document.getElementsByTagName('div');
for (var i = 0; i < nodes.length; i++) {
    nodes[i].addEventListener('click', function() {
        alert('You clicked element #' + (i+1));
    });
}

Click For Demo – JSFiddle

Code above demonstrates a classic JavaScript closure problem. Reference to the ‘i’ object is being stored in the click handler closure, rather than the actual value of ‘i’.

Every single click handler will refer to the same object because there’s only one counter object which holds 6 so you get six on each click.

To solve this problem we have to wrap this in an anonymous function and pass ‘i’ as the argument so that value gets copied to a new local variable and gets assigned to the click handler function. Such issues can also be avoided now by using let instead var as shown in the code below. This is possible because behind the scenes ‘let’ create a separate copy of variable while in the loop.

'use strict'
var nodes = document.getElementsByTagName('div');
for (let i = 0; i < nodes.length; i++) {
    nodes[i].addEventListener('click', function() {
        alert('You clicked element #' + (i+1));
    });
}

Click For Demo – JSFiddle

Thank you for reading the post.

Do share the wisdom and motivate us to keep writing even better online tutorials for free and do comment if anything is missing or wrong or you have some feedback for us.

Keep Learning. Happy Learning.. :)