JavaScript variables are easy to declare-but just as easy to misuse. From confusing var and let to overlooking hoisting behavior, even experienced developers can fall into common traps.
This guide walks you through the most frequent JavaScript variable mistakes and how to prevent them with cleaner, safer code.
Re-declaring Variables Unintentionally
Using var allows you to re-declare a variable in the same scope, which can lead to bugs.
var name = "John";
var name = "Jane"; // No error, but overwrites the previous value
Fix: Use let or const instead, which do not allow re-declaration in the same scope.
let name = "John";
// let name = "Jane"; // Error: Identifier 'name' has already been declared
Assigning Values Before Declaration
JavaScript hoists variable declarations, but not their initializations. Accessing a variable before declaration results in undefined or a ReferenceError.
console.log(age); // undefined
var age = 30;
With let and const, accessing the variable before it’s declared throws an error due to the Temporal Dead Zone.
console.log(age); // ReferenceError
let age = 30;
Not Using const by Default
Many developers default to let when they should use const. This can lead to unintended changes to variables that should be immutable.
let config = { debug: true };
config = null; // This can be avoided if const was used
Fix: Use const by default, and only use let if you plan to reassign the variable.
Using var Instead of let or const
The var keyword should be avoided in modern JavaScript because it’s function-scoped and can lead to confusing behaviors with hoisting and closures.
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100);
} // Outputs: 3, 3, 3
Fix: Use let to ensure block-scoping.
for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100);
} // Outputs: 0, 1, 2
Modifying const Objects or Arrays Incorrectly
const means the binding is constant-not the value. Developers sometimes assume const makes an object or array immutable.
const person = { name: "John" };
person.name = "Jane"; // Allowed
Fix: If immutability is required, use Object.freeze or a library like Immer.
const person = Object.freeze({ name: "John" });
person.name = "Jane"; // Fails silently or throws in strict mode
Using Variables Before Declaration in Loops
Using var in loops can lead to unexpected behavior due to lack of block scope.
for (var i = 0; i < 5; i++) { setTimeout(() => console.log(i), 100);
} // Logs: 5, 5, 5, 5, 5
Fix: Use let to create a new scope for each iteration.
for (let i = 0; i < 5; i++) { setTimeout(() => console.log(i), 100);
} // Logs: 0, 1, 2, 3, 4
Shadowing Variables
Shadowing occurs when a variable in a local scope has the same name as one in an outer scope, which can lead to confusion or errors.
let count = 10;
function logCount() {
let count = 5;
console.log(count); // 5, not 10
}
Fix: Avoid reusing variable names unnecessarily, especially when it causes confusion about which variable is being accessed.
Global Variable Leakage
Assigning a value to an undeclared variable implicitly creates a global variable (in sloppy mode), which is a common source of bugs.
function doSomething() {
result = 42; // Creates a global variable if not declared with let/const/var
}
Fix: Always declare your variables using let, const, or var. Also, consider using “use strict” mode.
"use strict";
let result = 42;
Conclusion
Variables in JavaScript are easy to get wrong, especially with scoping, hoisting, and immutability. By avoiding these common mistakes, you’ll write code that’s more predictable, maintainable, and free of subtle bugs.
Write smart, robust code by following best practices-and when in doubt, default to const.