Why does JS have both "var" & "let"?

var and let are both used to declare variables in Javascript. You've probably seen them used interchangeably around the web and want to know what's the difference and are there any caveats to using either.

Scoping

The main difference between the two is:

  • var is scoped to the immediate function enclosure (can be referenced outside a block within a function's boundaries)
  • let is scoped to the immediate block enclosure (can only be references in a block of {})

Learning by example is best, check out these functions:

const runVarExample = () => {
  for (var i =0; i < 3; i++) {
    console.log("var i = " + i);
  }

  console.log("After var loop, var is : " + i);
}

const runLetExample = () => {
  for (let i =0; i < 3; i++) {
    console.log("let i = " + i);
  }

  console.log("After let loop, let is : " + i);
}

console.log("Running var example");
runVarExample();

console.log("--------------");

console.log("Running let example");
runLetExample();

Running the above code will produce the following console output.

Running var example
var i = 0
var i = 1
var i = 2
After var loop, var is : 3
--------------
Running let example
let i = 0
let i = 1
let i = 2
error: Uncaught ReferenceError: i is not defined

As you can see, using var to declare variables can leave you with some unintended side effects.

Declaration & Redeclaration

Variables initialized with var can be re-initialized but variables declared with let will throw an error if you try to re-initialize them.

var exampleVar = "example";
var exampleVar = "not example"; // No problem


let exampleLet = "example";
let exampleLet = "not example"; // Will cause error

Global Properties

Global variables initialized with var are added to the global object.

var stringVar = "var_initialized";
let stringLet = "let_initialized";

console.log(window.stringVar); // "var_initialized"
console.log(window.stringLet); // undefined

Hoisting

Variables initialized with var are hoisted. This means the variables are initialized with undefined before the code is even run.

const runHoistingExample = () => {
   console.log(example); // undefined
   var example = "exampleValue";
   console.log(example); // "exampleValue"
}


const attemptLetHoistingExample = () => {
   console.log(example); // error: Uncaught ReferenceError: Cannot access 'example' before initialization
   let example = "exampleValue";
   console.log(example); 
}

Hope this shed some light on the differences between var and the new and improved let.

Happy Coding!