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.
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 (
userAgeis clearer than a bare18) - 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
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
constfor everything. -
Switch to
letonly if you know the value must change later (a counter, a running total, a "current page" tracker). -
Don't use
varin 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.
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
-
letandconstare block-scoped — they stay inside their{} -
varignores 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
Functions and loops also create their own scope — those are covered in the Scope & Hoisting and Functions sections.
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:
ageandAgeare 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!
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
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
-
Trying to reassign a
const— this throwsTypeError: Assignment to constant variable. -
Using a
let/constvariable before its declaration — this throws aReferenceErrordue 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" -
varbehaves differently: it is hoisted and initialized toundefined, so using it before its declaration silently givesundefinedinstead of an error — a major source of bugs. More in the Scope & Block Scope section below. -
Declaring the same variable twice with
letin the same scope — JavaScript will refuse. -
Trying to use a variable outside the block it was declared in —
for example, declaring a
constinside anifblock and then reading it after the closing}. This gives aReferenceError.
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
constby default,letwhen the value changes, and avoidvar. -
constlocks the binding, not the contents — you can still modify properties inside aconstobject or array. -
letandconstare block-scoped — a variable only exists inside the{}where it was declared. -
varis 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)