Manifest Stack home

How variables work in JS

Part 1: var — the old way

var was the only way to declare variables before ES6 (2015). It has two behaviours that cause bugs: it's function-scoped (not block-scoped) and it's hoisted as undefined.

var ignores block scope

javascript
if (true) {
    var x = 10; // NOT block-scoped!
}
console.log(x); // 10 — var leaked out of the if block

for (var i = 0; i < 3; i++) {}
console.log(i); // 3 — i leaked out of the for loop!

var can be re-declared (another source of bugs)

javascript
var name = "Arjun";
var name = "Kumar"; // ✅ No error — silently overwrites!
console.log(name);  // Kumar

// This means you can accidentally overwrite a variable
// declared elsewhere in the same function — no warning given.

Part 2: let — the modern default

let was introduced in ES6 to fix var's problems. It is block-scoped, cannot be re-declared, and is in the TDZ before its declaration.

let respects block scope

javascript
if (true) {
    let y = 20; // block-scoped
}
console.log(y); // ❌ ReferenceError: y is not defined

for (let i = 0; i < 3; i++) {}
console.log(i); // ❌ ReferenceError — i stays inside the loop

let cannot be re-declared

javascript
let score = 100;
let score = 200; // ❌ SyntaxError: Identifier 'score' already declared

// But it CAN be reassigned:
let age = 22;
age = 23; // ✅ Fine — reassignment is different from re-declaration

Part 3: const — for values that don't change

const is like let but the binding cannot be reassigned. Use it as your default — it forces you to be intentional when a value needs to change.

const prevents reassignment

javascript
const PI = 3.14159;
PI = 3; // ❌ TypeError: Assignment to constant variable

const country = "India";
country = "USA"; // ❌ TypeError

// Must be initialised at declaration:
const x; // ❌ SyntaxError: Missing initializer in const declaration

const with objects — the binding is const, not the contents

const prevents reassigning the variable, but if it holds an object or array, you can still change the contents of that object.

javascript
const user = { name: "Arjun", age: 22 };

user.age = 23;   // ✅ modifying a property — allowed!
user.city = "Chennai"; // ✅ adding a property — allowed!

user = {};       // ❌ TypeError: reassigning the binding — not allowed

// Same with arrays:
const nums = [1, 2, 3];
nums.push(4);    // ✅ [1, 2, 3, 4]
nums = [5, 6];   // ❌ TypeError

Quick comparison table

javascript
//              var         let         const
// Scope:       function    block       block
// Hoisting:    undefined   TDZ error   TDZ error
// Re-declare:  ✅ yes      ❌ no       ❌ no
// Reassign:    ✅ yes      ✅ yes      ❌ no
// Use today:   ❌ avoid    ✅ default  ✅ preferred

// Rule of thumb:
// 1. Use const by default
// 2. Use let only when you know the value will change
// 3. Never use var in modern code