Quick Answer

var is the old way to declare variables — it is function-scoped and easy to misuse. let and const are the modern choices: both are block-scoped, but let can be reassigned while const cannot. Use const by default, switch to let only when you actually need to reassign, and avoid var in new code.

The three ways to declare a variable

Every JavaScript program stores values in variables — a score, a username, a list of items. But JavaScript gives you three keywords to create them: var, let, and const. If you have ever wondered about let vs const vs var and which one you should actually type, this guide is for you.

The short version: var is the original keyword from the early days of JavaScript, and it behaves in ways that surprise beginners. let and const arrived in 2015 (a version called ES6) to fix those surprises. They are cleaner, safer, and what modern code uses everywhere.

Here is the simplest example of all three:

var city = "Delhi";     // works, but old-style
let score = 10;         // block-scoped, can change later
const pi = 3.14159;     // block-scoped, cannot be reassigned

They look almost identical, but the difference is in three things: scope (where the variable is visible), hoisting (what happens before the line runs), and whether you can reassign the value. Let us go through each keyword, then compare them side by side.

var: the old, function-scoped way

var is the keyword JavaScript shipped with in 1995. It still works, but it has two habits that cause bugs.

1. var is function-scoped, not block-scoped

A "block" is anything inside curly braces { } — like an if statement or a loop. Most languages keep variables inside the block they were created in. var does not. It leaks out to the whole function:

function checkAge() {
  if (true) {
    var age = 18;
  }
  console.log(age); // 18 — var escaped the if block
}
checkAge();

Many beginners expect age to only exist inside the if. With var, it does not, and that leads to accidental overwrites.

2. The classic loop bug

Because var is not block-scoped, a single var is shared across every turn of a loop. This trips up almost everyone:

for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i); // prints 3, 3, 3 — not 0, 1, 2
  }, 100);
}

By the time the timers run, the loop has finished and i is already 3. There is only one i, and all three callbacks read the same one. As you will see, let fixes this automatically.

let: block-scoped and reassignable

let declares a variable that lives only inside the block where you created it, and whose value you can change later. It behaves the way most people expect a variable to behave.

let score = 10;
score = 15;            // fine — let can be reassigned
console.log(score);    // 15

Notice that let stays inside its block. Try to use it outside and JavaScript stops you:

if (true) {
  let city = "Mumbai";
  console.log(city);   // "Mumbai"
}
console.log(city);     // ReferenceError: city is not defined

That error is a good thing — it catches mistakes early instead of letting a stray variable float around. And because each loop turn gets its own let, the loop bug from before simply disappears:

for (let i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i); // prints 0, 1, 2 — one i per turn
  }, 100);
}

Reach for let whenever a value genuinely needs to change over time — a running total, a counter, a value you swap based on user input.

const: block-scoped and can't be reassigned

const is short for "constant." It is block-scoped just like let, but once you assign a value you cannot reassign the variable to a new value:

const pi = 3.14;
pi = 3.15; // TypeError: Assignment to constant variable.

Because you can never reassign it, const must be given a value on the same line it is declared:

const total; // SyntaxError: Missing initializer in const declaration

The one thing beginners get wrong about const

const does not make the value "frozen." It only stops you from pointing the variable at a different value. If the value is an object or an array, you can still change what is inside it:

const user = { name: "Anita" };
user.name = "Ravi";   // allowed — we edited a property
user.age = 22;        // allowed — we added a property
console.log(user);    // { name: "Ravi", age: 22 }

user = { name: "New" }; // TypeError — can't reassign the variable

const nums = [1, 2, 3];
nums.push(4);         // allowed — the array is mutable
console.log(nums);    // [1, 2, 3, 4]

Think of const as a fixed label on a box. You cannot move the label to a different box, but you can still add and remove things inside the box. This is exactly why const is safe to use for most objects and arrays — you almost never want to replace the whole thing, just update its contents.

Scope, hoisting, and the temporal dead zone

Two words come up a lot in this topic: hoisting and the temporal dead zone. They sound scary but the idea is simple.

Hoisting

Before your code runs, JavaScript scans for declarations and "lifts" them to the top of their scope. With var, the variable exists early but holds undefined until its line runs — so using it early is allowed but gives you nothing useful:

console.log(greeting); // undefined (no error)
var greeting = "Hi";
console.log(greeting); // "Hi"

The temporal dead zone (TDZ)

let and const are also hoisted, but JavaScript refuses to let you touch them before their declaration line. That gap — from the start of the block until the declaration — is called the temporal dead zone:

console.log(name); // ReferenceError — name is in the TDZ
let name = "Priya";

This is another safety upgrade. Instead of silently handing you undefined like var, let and const throw a clear error so you fix the ordering of your code. Want to go deeper on how JavaScript runs your code step by step? Our free JavaScript course walks through scope and execution with hands-on examples.

let vs const vs var: side-by-side comparison

Here is the whole let vs const vs var comparison in one place:

Featurevarletconst
ScopeFunctionBlockBlock
HoistedYes (set to undefined)Yes (but in the TDZ)Yes (but in the TDZ)
Can be reassignedYesYesNo
Can be redeclared in the same scopeYesNoNo
Must be initialized when declaredNoNoYes
Object/array contents can still changeYesYesYes
Recommended for new codeNoWhen neededYes

The pattern is clear: let and const behave predictably and catch mistakes, while var is looser in every row.

Which one should you use?

You do not need to overthink this. Follow one simple rule that professional JavaScript developers use every day:

Use const by default. Switch to let only when you know the value will be reassigned. Avoid var in new code.

Why start with const? Because it communicates intent. When another person (or future you) reads const, they instantly know this value will not be swapped out later. That makes code easier to trust and read. If you find you actually need to change the value, your editor or the error message will remind you — just change that one line to let.

const taxRate = 0.18;          // never changes → const
let cartTotal = 0;             // will add to it → let

for (const item of cart) {     // item is fresh each turn → const is fine
  cartTotal = cartTotal + item.price;
}

console.log(cartTotal * (1 + taxRate));

Notice you can even use const inside a for...of loop, because each turn creates a brand-new item rather than reassigning the same one. Practising this habit on real problems is the fastest way to make it stick — the free Priodemy JavaScript course gives you runnable exercises for exactly this.

Common gotchas to watch for

A few final traps to keep in your back pocket:

  • const does not freeze objects. As we saw, const nums = [1, 2, 3] still lets you nums.push(4). If you truly need an unchangeable object, look up Object.freeze() — but you rarely need it as a beginner.
  • You cannot redeclare let or const in the same scope. Writing let x = 1; let x = 2; in the same block is an error. With var it silently works, which is exactly how bugs hide.
  • var in a loop shares one variable. If a timer, event handler, or callback inside a loop is behaving strangely, check whether you used var instead of let.
  • Old tutorials still use var. Plenty of code online was written before 2015. It is not "wrong," but when you write your own code, prefer let and const.

Master these and you have covered everything most JavaScript jobs will ever ask you about variable declarations. Keep it simple: const first, let when you must, var almost never.

Frequently Asked Questions

Is let or const faster than var?

In practice, the performance difference is negligible — you should never choose between them based on speed. Pick the keyword that best signals your intent: const for values that will not be reassigned and let for values that will.

Can I change a const object or array?

Yes. const only stops you from reassigning the variable to a whole new value. You can still edit properties of a const object or push and remove items from a const array, because the variable still points at the same object.

Why does var still exist if let and const are better?

Backwards compatibility. Millions of older websites use var, and browsers can never remove it without breaking them. It remains valid, but for new code you should prefer let and const.

What is the temporal dead zone in simple terms?

It is the gap between the start of a block and the line where a let or const variable is declared. If you try to use the variable inside that gap, JavaScript throws a ReferenceError instead of silently giving you undefined, which helps you catch bugs early.

Should a beginner just use const everywhere?

Almost. Use const by default, and only switch a specific variable to let when you actually need to reassign it. This is the same habit experienced developers follow, so it is a great one to build from day one.