JavaScript Varaibles Explained: var, let & const
What Are Variables in JavaScript? A Beginner's Guide to var, let, and const
If you're just starting out with JavaScript, one of the very first things you'll run into is the concept of a variable. Variables are the building blocks of pretty much every program you'll ever write, so it's worth taking the time to really understand them.
In this post, we'll break down what variables are, why they matter, and the differences between var, let, and const — with simple examples and exercises along the way.
Why Variables Are Important
Think of a variable as a labeled box where you can store a piece of information. Instead of typing the same value over and over, you give it a name and refer to that name whenever you need it.
let userName = "Sarah";
console.log("Welcome, " + userName);
Here, userName holds the value "Sarah". If Sarah's name changes, or if a different user logs in, you just update the box's contents — you don't have to rewrite your entire program.
Variables let you:
- Store and reuse data without repeating yourself
- Make code readable by giving values meaningful names
- Track changing state, like a shopping cart total or a game score
- Write flexible programs that respond to input, calculations, or user actions
Without variables, code would be static and unable to react to anything. With them, your program can remember, update, and respond to the world around it.
var Explained
var is the original way to declare variables in JavaScript, dating back to the very first version of the language.
var age = 25;
console.log(age); // 25
Key traits of var:
- It's function-scoped, not block-scoped (more on this below)
- It can be redeclared without errors
- It gets hoisted to the top of its scope (initialized as
undefined)
var age = 25;
var age = 30; // no error, totally allowed
console.log(age); // 30
While var still works today, most modern JavaScript style guides recommend avoiding it in favor of let and const, mainly because of scoping quirks that tend to cause bugs.
let Explained
let was introduced in ES6 (2015) to fix many of the pain points of var.
let score = 10;
score = 20; // reassignment is fine
console.log(score); // 20
Key traits of let:
- It's block-scoped (limited to the nearest
{ }) - It can be reassigned
- It cannot be redeclared in the same scope
- It's still hoisted, but not initialized (this creates the "temporal dead zone," explained later)
let score = 10;
let score = 20; // ❌ SyntaxError: Identifier 'score' has already been declared
let is the go-to choice when you know a variable's value will need to change over time.
const Explained
const (also introduced in ES6) is used for values that should never be reassigned.
const birthYear = 1998;
console.log(birthYear); // 1998
Key traits of const:
- It's block-scoped, just like
let - It cannot be reassigned
- It cannot be redeclared
- It must be initialized at the time of declaration
const birthYear = 1998;
birthYear = 2000; // ❌ TypeError: Assignment to constant variable.
One important nuance: const prevents reassignment, not mutation. If a const variable holds an object or array, you can still change its contents:
const person = { name: "Alex" };
person.name = "Jordan"; // ✅ totally fine
person = { name: "Sam" }; // ❌ not allowed
As a rule of thumb, default to const unless you know the value needs to change — then use let.
var vs let vs const: Comparison Table
| Feature | var |
let |
const |
|---|---|---|---|
| Scope | Function-scoped | Block-scoped | Block-scoped |
| Reassignable | ✅ Yes | ✅ Yes | ❌ No |
| Redeclarable | ✅ Yes | ❌ No | ❌ No |
| Hoisting | Hoisted, initialized as undefined |
Hoisted, but in "temporal dead zone" | Hoisted, but in "temporal dead zone" |
| Must initialize on declaration | ❌ No | ❌ No | ✅ Yes |
| Introduced in | ES1 (1997) | ES6 (2015) | ES6 (2015) |
Scope Differences
Scope determines where in your code a variable can be accessed.
- Function scope (
var): a variable is available anywhere inside the function it was declared in, regardless of blocks likeiforfor. - Block scope (
let,const): a variable is only available inside the nearest curly braces{ }it was declared in.
function testVar() {
if (true) {
var x = 5;
}
console.log(x); // 5 — accessible outside the if block
}
function testLet() {
if (true) {
let y = 5;
}
console.log(y); // ❌ ReferenceError: y is not defined
}
This is one of the biggest reasons developers moved away from var. It's easy to accidentally leak variables outside the block where you meant to use them, leading to confusing bugs.
Hoisting Explained Simply
Hoisting means JavaScript moves variable (and function) declarations to the top of their scope before running the code.
For var, the declaration is hoisted and initialized with undefined:
console.log(a); // undefined (not an error)
var a = 10;
For let and const, the declaration is hoisted but not initialized. Trying to use it before the actual line of declaration puts you in the temporal dead zone (TDZ), and JavaScript throws an error:
console.log(b); // ❌ ReferenceError: Cannot access 'b' before initialization
let b = 10;
The simplest way to think about it: JavaScript "reserves the box" ahead of time, but with let and const, you're not allowed to open the box until the line where you actually declared it.
Reassignment vs Redeclaration
These two terms often get mixed up, so let's separate them clearly.
- Reassignment = giving an existing variable a new value
- Redeclaration = declaring the same variable name again with
var,let, orconst
// Reassignment
let city = "Karachi";
city = "Lahore"; // ✅ allowed with let
// Redeclaration
let country = "Pakistan";
let country = "India"; // ❌ not allowed with let
var allows both reassignment and redeclaration. let allows reassignment but not redeclaration. const allows neither.
Common Beginner Mistakes
- Using
varout of habit — leads to unexpected scope leaks and bugs that are hard to trace. - Trying to reassign a
const— remember,constblocks reassignment, not mutation of objects/arrays. - Assuming hoisting means variables have a value before declaration — with
let/const, this throws an error (TDZ), it doesn't just returnundefined. - Declaring variables inside loops with
var— this often causes the classic "loop variable" bug:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Logs: 3, 3, 3 (not 0, 1, 2!)
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100);
}
// Logs: 0, 1, 2 — because let creates a new binding per iteration
- Not initializing
constvariables — this will throw a syntax error immediately.
Best Practices
- ✅ Default to
constfor anything that won't be reassigned - ✅ Use
letwhen you know the value will change (counters, loop variables, accumulators) - 🚫 Avoid
varin modern code unless you're maintaining legacy scripts - ✅ Declare variables close to where you use them, not all at the top
- ✅ Use descriptive names (
userCountinstead ofx) - ✅ Keep scope as tight as possible to avoid accidental bugs
Mini Exercises
Try these on your own, then check your understanding against the explanations below.
console.log(typeof myVar);
var myVar = "hello";
const total = 100;
total = total + 50;
console.log(total);
for (let i = 0; i < 3; i++) {
console.log(i);
}
console.log(i); // what happens here, and why?
const settings = { theme: "dark" };
settings.theme = "light";
1)
"undefined" — var is hoisted but not yet assigned.2) Change
const to let.3) Logs 0, 1, 2, then throws a ReferenceError since
i is block-scoped to the loop.4) Yes — you're mutating the object, not reassigning
settings itself.
Conclusion
Variables are the foundation of everything you'll build in JavaScript — they let your programs store, update, and react to data. While var was the only option for many years, let and const now give you safer, more predictable scoping and behavior.
The simplest rule to carry forward: use const by default, switch to let when you need to reassign, and leave var in the past. Once this becomes second nature, you'll write cleaner code and avoid a whole category of common bugs.
Happy coding!

Comments
Post a Comment