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.

6 min read

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.

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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 defined

Problem 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.

javascriptjavascript
var userName = "Alex";
// ... many lines of code ...
var userName = "Jordan";
 
console.log(userName); // "Jordan" - first value silently lost

This 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:

javascriptjavascript
let userName = "Alex";
let userName = "Jordan"; // SyntaxError: Identifier 'userName' has already been declared

The 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:

javascriptjavascript
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:

javascriptjavascript
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 varUseWhen
var name = "Alex"const name = "Alex"Value never changes
var count = 0let count = 0Value gets reassigned later
var i = 0 (loop)let i = 0Loop counter
var config = {}const config = {}Object reference stays fixed

Here is a side-by-side comparison of the same function written both ways:

javascriptjavascript
// 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:

javascriptjavascript
// 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

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.
RunePowered by Rune AI

Frequently Asked Questions

Is var deprecated in JavaScript?

No, var is not officially deprecated and still works in all JavaScript engines. However, the entire JavaScript community has moved to let and const for new code. var remains only for backward compatibility with older scripts.

Will removing var break old code?

Replacing var with let or const in existing code can change behavior if the code depends on var's function scoping or hoisting. Refactor carefully, one file at a time, and test after each change.

Does using var affect performance?

No. var, let, and const have the same performance in modern engines. The issue with var is correctness and readability, not speed.

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.