Variables: let, const, and var

A variable is a labeled box where your program stores a piece of information so it can use it later.

What Is a Variable?

A variable is a name you give to a piece of data so you can refer back to it later instead of retyping it. In JavaScript you create one using the keyword let, const, or the older var.

let age = 18;
  • let — a keyword meaning "I'm creating a new variable that can change later"
  • age — the name we chose for this box
  • = — the assignment operator; it means "put this value into that box," not "equals" like in math
  • 18 — the value being stored
  • ; — ends the instruction

Behind the scenes, the computer sets aside a small space in memory, labels that space age, and stores the number 18 there. Whenever you write age again, JavaScript goes and fetches whatever is currently in that box.

📦 Real-life analogy

A variable is like a labeled storage box. You write "age" on a sticky note and put it on a box, then place the number 18 inside. Later, you can look at the box labeled "age" to remember what's inside — or open it up and swap in a new value.

Why Do We Use Variables?

Without variables, every piece of data you use would need to be typed out, every single time, with no way to update it. Variables let you:

  • Store a value once and reuse it many times
  • Give data a meaningful name (userAge is clearer than a bare 18)
  • Update a value as your program runs (like a score that goes up)

let vs const vs var

Keyword Can it change later? Should you use it?
const No — value is locked in Yes, use by default
let Yes — value can be reassigned Yes, when the value needs to change
var Yes, but with confusing old rules No — avoid in modern code

const — "this never changes"

const birthYear = 2008;
// birthYear = 2009;   ❌ This would cause an error — const cannot be reassigned
📌 const with objects and arrays — coming later

When you learn about objects and arrays (covered in their own sections), you'll discover a useful detail: const only locks the variable itself — you can still modify what's inside an object or array. That's covered fully when you get there.

let — "this can change"

let score = 0;
score = 10;   // ✅ totally fine, let allows this

var — the old way

var name = "Sam";

var was the only option before 2015. It still works, but it has two confusing behaviours that cause real bugs:

// 1. var is "hoisted" — you can use it BEFORE the line that declares it
//    Instead of crashing, it silently gives you undefined
console.log(city); // undefined — no error, just silence
var city = "London";
console.log(city); // "London"

// With let/const the same code crashes loudly (which is the correct behaviour):
console.log(country); // ❌ ReferenceError — easy to spot and fix
let country = "France";

// 2. var ignores block boundaries — it "leaks" out of if/for blocks
if (true) {
  var leaked = "I escaped the block!";
}
console.log(leaked); // "I escaped the block!" — var leaks out

if (true) {
  let contained = "I stay inside";
}
console.log(contained); // ❌ ReferenceError — let stays in its block

Both behaviours are covered fully in the Scope section below. For now: just use const and let and you'll never run into either problem.

When Should We Use Each One?

  • Start with const for everything.
  • Switch to let only if you know the value must change later (a counter, a running total, a "current page" tracker).
  • Don't use var in new code — it's kept in the language only so old websites keep working.

Scope & Block Scope

Scope is the rule that decides where in your code a variable can be seen and used. Variables don't exist everywhere — they only exist in the region where they were declared.

Think of it like rooms in a house. A lamp in a bedroom is only usable in that bedroom — you can't turn it on from the kitchen.

🏠 Real-life analogy

Each pair of curly braces {} is like a room. Anything declared inside a room is only visible inside that room (and smaller rooms nested inside it). The hallway outside can't see what's inside.

Global Scope vs. Block Scope

There are two kinds you'll meet right away:

// Global scope — declared outside any {} block
// Visible everywhere in the file
const appName = "MyApp";

// Block scope — declared inside {} lives only inside that block
if (true) {
  const message = "hello"; // lives only inside this if block
  console.log(message);   // ✅ works here
  console.log(appName);   // ✅ can see outer scope from inside
}
// console.log(message); ❌ ReferenceError — message doesn't exist out here
  • let and const are block-scoped — they stay inside their {}
  • var ignores block boundaries and leaks out of blocks.
  • A variable from an outer scope IS visible inside a nested block.

Inner Blocks Can See Outer Variables

const tax = 0.2; // outer scope

if (true) {
  const price = 100;
  console.log(price * (1 + tax)); // ✅ 120 — inner block sees outer "tax"
}

// But NOT the reverse:
console.log(price); // ❌ ReferenceError — "price" was inside the if block

var Leaks Out of Blocks

This is one of the biggest reasons to avoid var. Unlike let and const, var ignores block scope entirely.

if (true) {
  var leaked = "I escaped!";
}
console.log(leaked); // "I escaped!" — var leaked out of the block

if (true) {
  let contained = "I stay inside";
}
console.log(contained); // ❌ ReferenceError — let stayed inside

Shadowing

Shadowing happens when you declare a variable inside an inner scope with the same name as one in an outer scope. Inside that block, the inner variable hides (shadows) the outer one.

const city = "London"; // outer scope
if (true) {
  const city = "Paris"; // inner scope — shadows outer "city"
  console.log(city); // "Paris" — sees the inner one
}
console.log(city); // "London" — outer one untouched
📌 More on scope

Functions and loops also create their own scope — those are covered in the Scope & Hoisting and Functions sections.

💡 Simple rule

A variable declared with let or const lives from the line it's declared until the closing } of the block it's in. Anything outside that block can't see it.

Naming Variables

  • Names can contain letters, numbers, $, and _, but can't start with a number.
  • JavaScript is case-sensitive: age and Age are different variables.
  • The convention is camelCase: firstName, totalPrice, isLoggedIn.
  • Names should describe what the value is, not how it's used.

Real-World Examples

// 1. E-commerce: storing product info
const productName = "Wireless Headphones";
const price = 49.99;
let stockCount = 100;

// Someone buys one — update stock
stockCount -= 1;
console.log(productName + " — £" + price + " | Stock left: " + stockCount);

// 2. Game score tracker
let score = 0;
score += 10; // player got a point
score += 25; // bonus points
console.log("Current score: " + score);

// 3. User profile — some info never changes, some does
const userId = "USR-4821"; // never changes — use const
let userName = "maya_codes"; // can be updated — use let
userName = "maya_dev"; // user changed their username
console.log("User ID: " + userId + ", Username: " + userName);

Try It: Code Runner

Practice creating variables with let and const. Try changing values and see what happens!

JavaScript Playground
OUTPUT

            

Multiple Assignment & Chained Assignment

You can declare several variables on one line by separating them with commas, or assign the same value to multiple variables in a chain.

// Declaring multiple variables at once (one keyword, comma-separated)
let x = 1, y = 2, z = 3;
console.log(x, y, z); // 1 2 3

// Chained assignment — assigns the same value to multiple variables
let a, b, c;
a = b = c = 0; // c = 0 first, then b = 0, then a = 0 (right-to-left)
console.log(a, b, c); // 0 0 0
📌 Chained assignment with objects

Chaining works fine with primitive values like numbers. When you learn about objects (a later section), you'll discover that a = b = {} makes both point to the same object — which can cause bugs. That's covered fully in the Objects section.

Common Mistakes

⚠ Watch out for
  • Trying to reassign a const — this throws TypeError: Assignment to constant variable.
  • Using a let/const variable before its declaration — this throws a ReferenceError due to the Temporal Dead Zone (TDZ). The TDZ is the gap between the start of the block and the line where the variable is declared. Inside that gap the variable technically exists but is completely off-limits:
    // ❌ TDZ — can't use 'name' before this line
    console.log(name); // ReferenceError: Cannot access 'name' before initialization
    const name = "Maya";
    // ✅ Safe to use from here downward
    console.log(name); // "Maya"
  • var behaves differently: it is hoisted and initialized to undefined, so using it before its declaration silently gives undefined instead of an error — a major source of bugs. More in the Scope & Block Scope section below.
  • Declaring the same variable twice with let in the same scope — JavaScript will refuse.
  • Trying to use a variable outside the block it was declared in — for example, declaring a const inside an if block and then reading it after the closing }. This gives a ReferenceError.

Best Practices

  • Default to const; it protects you from accidentally overwriting a value.
  • Use clear, descriptive names instead of single letters (except in short loops).
  • Declare one variable per line for readability.

Performance Notes

let and const are not meaningfully slower or faster than var in modern engines — the reason to prefer them is safety and clarity, not speed.

Browser Compatibility

let and const have been supported in all major browsers since 2015 (ES6). var works everywhere, including very old browsers.

Interview Questions

What's the difference between let and const?

Both are block-scoped, but a variable declared with const cannot be reassigned after its initial value is set, while let can be reassigned as many times as needed.

Can you change the contents of a const object or array?

Yes. const only locks the variable itself from being reassigned to a new value — it doesn't freeze the contents. You can still change properties inside a const object or push items into a const array.

What is scope in JavaScript?

Scope determines where in your code a variable is accessible. A variable declared inside a block {} is block-scoped and only exists there. A variable declared outside any block is global and visible everywhere.

What is shadowing?

Shadowing occurs when a variable declared within a nested block scope has the exact same name as a variable in an outer scope. The inner variable overrides (shadows) the outer variable's access within that block.

✏️ Exercise

Declare a const inside an if block. Try to log it outside the block. Observe the ReferenceError. Then move the declaration outside the if and confirm it works.

🧠 Quiz

1. Which keyword should you reach for by default?

const.

2. What happens if you try to reassign a const variable?

JavaScript throws a TypeError and stops execution.

3. You declare const items = []; inside an if block. Can you access items outside that block?

No. let and const are block-scoped — the variable only exists inside the {} where it was declared.

4. Does var leak out of a block?

Yes. var ignores block boundaries and leaks, unlike let and const.

🚀 Mini Challenge

Declare a const greeting = "Hello" outside an if (true) {} block. Inside the block, declare another const greeting = "Hi". Log both — inside the block, and then outside. Predict what each log prints before running it.

Summary

  • Variables are named storage for data.
  • Use const by default, let when the value changes, and avoid var.
  • const locks the binding, not the contents — you can still modify properties inside a const object or array.
  • let and const are block-scoped — a variable only exists inside the {} where it was declared.
  • var is hoisted and leaks out of blocks — two behaviours that cause silent bugs.
  • Variable names are case-sensitive and use camelCase by convention.

Related Topics

MDN reference: developer.mozilla.org → JavaScript → let, const (placeholder — add live link)