JavaScript Variables: var, let, and const Explained

JavaScript variables let you store values so your code can reuse, update, and compare data. Understanding var, let, and const is one of the most important JavaScript basics because these keywords affect scope, reassignment, hoisting, and how safe your code is.

Quick answer: In modern JavaScript, use const by default, use let when a value must change, and avoid var in new code. The main differences are scope rules, hoisting behavior, and whether reassignment is allowed.

Difficulty: Beginner

Helpful to know first: You'll understand this better if you already know basic JavaScript syntax, simple data types like strings and numbers, and how to run small code examples in the browser console or Node.js.

1. What Are var, let, and const?

var, let, and const are JavaScript keywords used to declare variables. A variable gives a name to a value so you can use that value later in your program.

These three keywords do a similar job, but they do not behave the same way. The most important differences are scope, hoisting, and reassignment.

This topic is often confusing because beginners assume all three are interchangeable. They are not. Choosing the right one helps prevent bugs and makes your code easier to understand.

var vs let vs const
let and const
  • Block scoped
  • Safer in modern code
  • Preferred today
var
  • Function scoped
  • Older behavior
  • More bug-prone

Modern JavaScript usually prefers let and const over var.

2. Side-by-Side Comparison

The table below shows the practical differences between the three variable declaration keywords.

Feature var let const
Scope Function scope Block scope Block scope
Can be reassigned Yes Yes No
Must be initialized when declared No No Yes
Hoisted Yes Yes, but not usable before declaration Yes, but not usable before declaration
Can be redeclared in same scope Yes No No
Recommended for new code No Yes Yes

3. Key Differences Explained

Scope

Scope means where a variable is accessible in your code.

var is function-scoped, so if you declare it inside a function, it is available anywhere inside that function. It does not respect block boundaries such as if statements or loops.

let and const are block-scoped, so they only exist inside the block where they are declared.

if (true) {
  var oldWay = "visible outside";
  let modernWay = "only inside block";
}

console.log(oldWay); // "visible outside"
// console.log(modernWay); // ReferenceError

This is one reason let is safer than var. It prevents values from leaking outside the block where they belong.

Reassignment

Reassignment means giving a variable a new value after it has already been declared.

let score = 10;
score = 20;

const siteName = "DevDocs10";
// siteName = "New Name"; // TypeError

Use let when the value is expected to change. Use const when the variable should always point to the same value.

Hoisting

All three declarations are hoisted, but they do not behave the same way.

With var, the declaration is hoisted and initialized with undefined. With let and const, the declaration is hoisted too, but the variable stays in the temporal dead zone until the declaration line is reached.

console.log(count); // undefined
var count = 5;

// console.log(total); // ReferenceError: Cannot access 'total' before initialization
let total = 8;

This difference explains why older code using var can behave in surprising ways.

Redeclaration

var allows redeclaration in the same scope, while let and const do not.

var message = "Hello";
var message = "Hi";

let user = "Ava";
// let user = "Liam"; // SyntaxError

Preventing redeclaration makes accidental bugs easier to catch.

4. When to Use Each

You rarely need to ask which keyword is technically possible. The more useful question is which keyword best communicates your intention.

A helpful modern rule is: start with const, change to let only if reassignment is necessary, and leave var for legacy code.

5. Code Examples

The examples below show how these keywords behave in realistic situations.

Example 1: A value that changes over time

A running total is a good case for let because the value changes as the program runs.

let cartTotal = 0;
cartTotal += 25;
cartTotal += 15;

console.log(cartTotal); // 40

This works because let allows reassignment.

Example 2: A constant setting

A tax rate is usually a good fit for const because you do not want to accidentally point the variable at a different value later.

const taxRate = 0.2;
const price = 100;
const finalPrice = price + (price * taxRate);

console.log(finalPrice); // 120

This code is easier to trust because the names that should stay stable are declared with const.

Example 3: Block scope inside an if statement

This example shows why let and const help prevent leaking values outside a block.

const isLoggedIn = true;

if (isLoggedIn) {
  const welcomeMessage = "Welcome back";
  console.log(welcomeMessage);
}

// console.log(welcomeMessage); // ReferenceError

The variable exists only where it is needed, which keeps the surrounding code cleaner.

Example 4: const with arrays and objects

Many beginners think const makes an object or array fully unchangeable. It does not. It only prevents reassignment of the variable itself.

const colors = ["red", "blue"];
colors.push("green");

console.log(colors); // ["red", "blue", "green"]

The array contents can change, but the variable colors cannot be reassigned to a different array.

Example 5: Why var can be surprising in loops

This is a classic reason modern JavaScript prefers let in loops.

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

// console.log(i); // ReferenceError

Because let is block-scoped, the loop variable stays inside the loop where it belongs.

6. Common Mistakes

Mistake 1: Reassigning a const variable

A variable declared with const cannot be assigned a new value later. Beginners often choose const and then try to update it.

Problem: This code tries to reassign a constant, which causes a runtime error such as TypeError: Assignment to constant variable.

const count = 1;
count = 2;

Fix: Use let when the value needs to change after declaration.

let count = 1;
count = 2;

The corrected version works because let allows reassignment.

Mistake 2: Using let or const before declaration

Developers coming from older JavaScript sometimes expect all hoisted variables to act like var. That is not how let and const work.

Problem: This code accesses the variable before its declaration line, causing ReferenceError: Cannot access 'userName' before initialization.

console.log(userName);
let userName = "Mia";

Fix: Declare the variable before using it.

let userName = "Mia";
console.log(userName);

The corrected version works because the variable is accessed only after it has been initialized.

Mistake 3: Expecting const to freeze objects or arrays

const protects the variable binding, not the internal contents of an object or array.

Problem: This code assumes const prevents all changes, but object properties can still be updated unless you use an additional technique like Object.freeze().

const settings = {
  theme: "light"
};

settings.theme = "dark";

Fix: Remember that const stops reassignment, not mutation of object contents.

const settings = {
  theme: "light"
};

// Allowed: changing a property
settings.theme = "dark";

// Not allowed: reassigning the variable
// settings = { theme: "blue" };

The corrected explanation works because it matches how const actually behaves in JavaScript.

Mistake 4: Using var inside a block and expecting block scope

Beginners often assume a variable declared inside an if block stays inside that block. That is true for let and const, but not for var.

Problem: This code leaks the variable outside the block, which can lead to accidental overwrites and confusing behavior.

if (true) {
  var status = "active";
}

console.log(status); // "active"

Fix: Use let or const when you want block scope.

if (true) {
  const status = "active";
  console.log(status);
}

// console.log(status); // ReferenceError

The corrected version works because block-scoped variables stay limited to the block where they were declared.

7. Tradeoffs and Edge Cases

8. Decision Guide

If you are unsure which one to choose, use this simple guide:

A practical habit is to write const first. If JavaScript later needs reassignment, change it to let.

9. Key Points

10. Final Summary

var, let, and const all declare variables, but they communicate different intentions and follow different rules. The biggest differences are scope, reassignment, hoisting behavior, and redeclaration. These differences matter because they affect whether your code is predictable or bug-prone.

In modern JavaScript, the safest approach is usually to use const for stable bindings and let for values that must change. Treat var as something you should understand for legacy code rather than something you should choose for new code. A good next step is to practice variable declarations inside functions, loops, and conditionals so the scope rules become natural.