Let in Javascript

let:

The let statement declares a block-scoped, local variable.

syntax:

let x ;

let x = 2 ;

Description:

In the usage of let, we can divide the let concepts into three categories, they are

  1. Scoping rules.
  2. Re-declaration.
  3. Temporal dead zone.

Scoping rules:

Variables declared using let have a scope for the block or sub-block only. According to the below code, var is much similar to let but when var is used it takes the entire functional block.

function varScope() {
  var x = 1;
  {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letScope() {
  let x = 1;
  {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

In the below code, the let doesn't contain any window object, unlike var. Because the memory allocated for variable initialized using let will not be in the global scope.

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

Here this keyword is a property of the window object, it is not applicable for the let variable.

In the below code, when used inside a block, let limits the variable's scope to that block.

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

  console.log(a);  // 11
  console.log(b);  // 22
}

console.log(a); // 11
console.log(b); // 2

In the above code, the var a is initialized again in if condition, but this is not functional scope so the var a will be in global scope, this gives the value to a as 11 after executing the code var a = 11;.

Re-declaration:

By using let, we should not re-declare the same variable name once.

if (x) {
  let sameName;
  let sameName; // SyntaxError thrown.
}

However, the below combination of var and let declaration will give a SyntaxError because var is being hoisted to the top of the block. This results in an implicit re-declaration of the variable.

let x = 1;

{
  var x = 2; // SyntaxError for re-declaration
}

No two variable names should be the same in a given scope.

Temporal dead zone:

the temporal dead zone is something that will happen for the variable which is declared using let, i.e the time between let variable declaration and fully initialization.

The variable declared using let cannot be used until it is initialized. Declaring let variable and using it before initializing will throw a ReferenceError.

{ 
  console.log(a); // undefined
  console.log(b); // ReferenceError
  var a = 1;
  let b = 2; 
}

The TDZ and typeof:

Using the typeof operator for a let variable in its TDZ will throw a ReferenceError because at the time of type checking for i, the i is not initialized yet. So it gives a ReferenceError.

// results in a 'ReferenceError'
console.log(typeof i);
let i = 10;

This differs from using typeof for undeclared variables, and variables that hold a value of undefined because the undeclared variables cannot get any type until it is initialized with something like a number, string, boolean, etc.

// prints out 'undefined'
console.log(typeof undeclaredVariable);

TDZ combined with lexical scoping

The following code results in a ReferenceError at the line shown:

function test(){
   var x = 33;
   if(x) {
      let x = (x + 55); // ReferenceError
   }
}
test();

The if block is evaluated because the outer var x has a value. However, due to lexical scoping this value is not available inside the block: the identifier x inside the if block is the let x. The expression (x + 55) throws a ReferenceError because initialization of let x has not been completed — it is still in the temporal dead zone.

function test(n) {
  // n here is defined!
  console.log(n); // Object {a: [1,2,3]}

  for (let n of n.a) { // ReferenceError
    console.log(n);
  }
}

test({a: [1, 2, 3]});

In the above code, the test() function takes the object as a parameter. In console.log(n), the n is assigned to the object so the output of that code will be an object. In the for loop, the condition let n of n.a will get a ReferenceError because before fully initializing n the above code is using n which is in the temporal dead zone(TDZ) that causes the ReferenceError.

These are the different concepts for the usage of let that can be used in daily programming. Using let in daily programming will give a strictness to the variables which helps in debugging the code.

Press the like, share and comment your thoughts.

Thank you.