Why You Should Stop Using var in JavaScript
var has three dangerous behaviors that cause silent bugs: function scoping, redeclaration without errors, and hoisting with undefined. Here is why let and const replaced it.
var was the only way to declare variables in JavaScript from 1997 until 2015. It is still valid syntax and still runs in every browser. But it has three behaviors that cause real bugs, and those bugs are silent: the code runs without errors and produces wrong results instead.
let and const, introduced in ES6, fix every one of these problems. Here is exactly why you should stop using var and what to use instead.
Problem 1: var Leaks Out of Blocks
The most common var bug happens inside if statements and loops. var is function-scoped, not block-scoped, so a variable declared inside a block is visible everywhere in the containing function.
function processOrder(quantity) {
if (quantity > 10) {
var discount = 0.15;
}
console.log(discount); // undefined even when the if block never ran
}
processOrder(5);When quantity is 5, the if block never runs. But discount is still declared and hoisted to the top of the function with the value undefined. The code runs without error and gives you undefined instead of the variable not existing, making the bug much harder to find.
With let, the same code throws a clear ReferenceError immediately. The error message tells you exactly what is wrong and on which line. A loud error at development time is always better than a silent wrong value at runtime:
function processOrder(quantity) {
if (quantity > 10) {
let discount = 0.15;
}
console.log(discount); // ReferenceError: discount is not defined
}The same problem happens inside for loops. A var loop counter stays alive after the loop ends, while a let counter stays contained:
for (var i = 0; i < 3; i++) {
// loop body
}
console.log(i); // 3 (still alive outside the loop)
for (let j = 0; j < 3; j++) {
// loop body
}
console.log(j); // ReferenceError: j is not definedProblem 2: var Allows Silent Redeclaration
If you declare the same var variable twice, JavaScript does not warn you. It silently overwrites the first one without any indication that something went wrong.
var userName = "Alex";
// ... many lines of code ...
var userName = "Jordan";
console.log(userName); // "Jordan" - first value silently lostThis becomes dangerous in larger files where two declarations can end up far apart. The second declaration looks like it is creating a fresh variable, but it is actually overwriting an existing one. The first value is silently lost with no error and no warning.
With let, redeclaration throws a SyntaxError immediately. The code will not run at all, which is exactly what you want. A syntax error caught during development prevents a logic error at runtime:
let userName = "Alex";
let userName = "Jordan"; // SyntaxError: Identifier 'userName' has already been declaredThe error message names the exact variable that was redeclared, making the fix trivial.
Problem 3: var Hoists with undefined
All variable declarations in JavaScript are hoisted to the top of their scope during compilation. The critical difference is what value they hoist with.
var hoists the declaration and initializes it to undefined. This means you can access a var variable before its declaration line without any error. You get undefined instead:
console.log(total); // undefined (no error!)
var total = 100;The code runs without complaint and produces a value that looks intentional. If total is supposed to be a number and it is undefined, every calculation that uses it will produce NaN. The original bug is hard to trace back because the code never throws an error.
let and const also hoist their declarations to the top of the scope, but they are not initialized. This is called the temporal dead zone. Accessing the variable before its declaration throws an immediate ReferenceError:
console.log(total); // ReferenceError
let total = 100;The temporal dead zone between the start of the scope and the declaration line is a safety feature. It turns a silent wrong value into a loud, clear error that tells you exactly which variable was accessed too early.
What to Use Instead
Replace var with const or let based on whether the value changes after its initial assignment. This simple rule covers every case:
| Instead of var | Use | When |
|---|---|---|
| var name = "Alex" | const name = "Alex" | Value never changes |
| var count = 0 | let count = 0 | Value gets reassigned later |
| var i = 0 (loop) | let i = 0 | Loop counter |
| var config = {} | const config = {} | Object reference stays fixed |
Here is a side-by-side comparison of the same function written both ways:
// Old code with var
function calculateTotal(items) {
var total = 0;
for (var i = 0; i < items.length; i++) {
var item = items[i];
total = total + item.price;
}
return total;
}The old version works, but it has three problems: total and i leak out of their blocks, the loop variable i stays alive after the loop, and item is accidentally function-scoped when it should be block-scoped. Here is the same function rewritten with let and const:
// Modern equivalent with const and let
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
const item = items[i];
total = total + item.price;
}
return total;
}The logic is identical, but the let and const version is safer. The variable i and total use let because they change during execution. The variable item uses const because each iteration gets a fresh binding that never reassigns within the loop body.
The function returns the same result either way, but the modern version catches mistakes that the var version silently ignores.
Does var Ever Make Sense Today?
In new code, almost never. let and const cover every use case var ever had, and they do it with safer defaults that surface bugs instead of hiding them.
The one theoretical case is when you intentionally want function-scoped behavior. Even then, you can declare a let at the top of the function and get the same visibility without the hoisting and redeclaration risks. There is simply no benefit to var that let does not provide with better safety.
If you are maintaining older code that uses var, refactor gradually. Start by replacing var with const wherever the variable is never reassigned. Most variables in real code do not actually change, so this first pass often covers the majority of cases.
Then switch the remaining ones to let and run your tests after each change.
For the full comparison of all three keywords, see var vs let vs const. To decide when to pick let over const, read the let vs const decision guide.
Rune AI
Key Insights
- var is function-scoped and leaks out of blocks like if and for.
- var allows silent redeclaration, which hides bugs.
- var hoists with undefined, making accessed-before-declaration bugs silent.
- let and const fix all three problems with block scoping and strict rules.
- In modern code, use const by default and let when reassignment is needed.
Frequently Asked Questions
Is var deprecated in JavaScript?
Will removing var break old code?
Does using var affect performance?
Conclusion
var causes three kinds of silent bugs: variables that leak out of blocks, accidental redeclaration, and undefined values from hoisting. let and const fix all three problems. There is no reason to use var in new JavaScript code. Switch to const by default and let when the value needs to change.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.