What bugs does hoisting cause?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
Hoisting itself is not a bug, but var combined with it produces a handful of failures that all look confusing at the point where they surface rather than where they were caused.
1. A silent undefined instead of an error
function getTotal(items) {
console.log(total); // undefined, not an error
var total = items.length;
}
The program keeps running with a meaningless value, and you discover it several lines later where the symptom makes no sense. With let you get a ReferenceError pointing at the exact line.
2. A variable leaking out of its block
if (user) {
var role = user.role;
}
return role; // visible here — `undefined` when the branch did not run
Readers assume role belongs to the if. It does not; var is scoped to the whole function.
3. Accidental shadowing inside a loop
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 3, 3, 3
}
All three callbacks share one binding. let creates a fresh one per iteration and prints 0, 1, 2.
4. A redeclaration that overwrites silently
Two vars or two function declarations with the same name do not error — the later one simply wins, which is easy to miss in a long file.
5. A function expression called too early
init(); // TypeError: init is not a function
var init = function () {};
The variable is hoisted, the assignment is not.
How to avoid all of this
Use const by default and let where you must reassign — that alone removes cases 1 to 4, because block scoping and the temporal dead zone turn each one into an immediate error. Declare variables next to where they are first used rather than at the top of the function. Enable no-var and no-use-before-define in ESLint so the linter catches the rest before review does.
