let, const and var

Scope of   var

Scope essentially means where these variables are available for use. var declarations are globally scoped or function/locally scoped.

  1. The scope is global when a var variable is declared outside a function. This means that any variable that is declared with var outside a function block is available for use in the whole window.
  2. var is function scoped when it is declared within a function. This means that it is available and can be accessed only within that function.

Scope of let

let is block scoped. A block is a chunk of code bounded by {}. A block lives in curly braces. Anything within curly braces is a block. As in, all below are blocks.

  1. if { 
      // if statement is a block
    }
  2. for(...) { 
      // For statement is a block
    }
  3. array.forEach(() => {
      // Iterator content is a block
    });
  4. function hello()
      // Each function is a block
    }
  5. function hello()
      // Outer block
      {
        // Inner block
        let yo = 'inner hello';
      }
    }

const is similar to let

const is very similar to let w.r.t to lot of differences between variables declared with var. The only difference between let & const is that values created with const can't be updated/modified/re-declared after initialization. Though, when you create objects with const the properties of the object can be changed while the object itself can't be reassigned. This basically means that creating objects with const creates a a constant reference to object but, not the object itself.

Other differences

  1. let variables cannot be read/written until they have been fully initialized, which happens when they are declared (if no initial value is specified on declaration, the variable is initialized with a value of undefined). Accessing the variable before the initialization results in a ReferenceError. The period in which variable declared by let exists from start of scope to the point of initialization is referred to as "temporal dead zone" (TDZ).

  2. let variables cannot be re-declared while var variable can be re-declared in the same scope any number of times. var just treats them as initializations.

Few examples & snippets below

Below, we have few different experiments that showcase what we we're talking above.

var from inner scope

var is accessible here though it was defined was in if statement block while we are accessing it outside of the if statement. This is because var has global scope
For more info on how - read hoisting

if (true) {
  var testVar1 = 'hello';
}
// Prints 'hello'
console.log(testVar1);
let from inner scope

let is not accessible here as the scope that it was defined has ended. In this case, it was defined in if statement, which is a block and it scope only lasts until the end of block (Block scope).

if (true) {
  let testVar1 = 'hello';
}
// Will throw an error
console.log(testVar1);
var can be redeclared

The var keyword allows you to redeclare a variable without any issue

var counter = 10;
var counter;
console.log(counter); // 10
var counter = 20;
console.log(counter); // 20
let cannot be redeclared

The var keyword allows you to redeclare a variable without any issue

let greeting = "say Hi";
  // Below will throw an error
  // Identifier 'greeting' has already been declared
  let greeting = "say Hello instead";
  let hello = 'Hello';
  if(true) {
    // This is fine as this is a different scope
    let hello = 'Hola';
  }
const cannot be modified

The const variable cannot be redeclared, updated or modified post it's declaration. You can't create an empty variable with const. A variable through const needs to always with initialisation.

const greeting = "say Hi";
// error: Identifier 'greeting' has already 
const greeting = "say Hello instead";
// error: Assignment to constant variable. 
greeting = "say Hello instead";
// error: Missing initializer in const declaration
const greeting2;

References:

  1. What's difference between var and let article
    https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference
  2. Mozilla MDN entry
    https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
  3. Nice article that explains lexical environment by Sukhjinder Arora
    https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda