Facebook Pixel

var Leaking From Blocks and Loops in JavaScript

var leaks out of blocks and loops because it is function-scoped. Here is the problem and how let fixes it.

var Leaking From Blocks and Loops in JavaScript

var is function-scoped, not block-scoped. This means it leaks out of if blocks, for loops, and standalone blocks. This is one of the biggest reasons to avoid var.

Leaking From an if Block

if (true) { var x = 5; } console.log(x); // 5 (leaked out) `` With `let`, it would be a `ReferenceError`. `var` ignores the block boundary. ### Leaking From a `for` Loop ```js for (var i = 0; i < 3; i++) {} console.log(i); // 3 (leaked out) `` `i` is still accessible after the loop. With `let`, it would be confined to the loop. ### Leaking From a `while` Loop ```js let count = 0; while (count < 3) { var inside = count; count++; } console.log(inside); // 2 (leaked out) `` ### Leaking From a Standalone Block ```js { var y = 10; } console.log(y); // 10 (leaked out) `` ### Why This Is a Problem - **Namespace pollution**: `var` variables linger after the block ends, cluttering the scope. - **Bugs**: you can accidentally read or overwrite a variable from a block that has finished. - **Closure bugs**: `var` in a loop + callbacks all share one variable, leading to the classic `3, 3, 3` bug. - **Accidental globals**: `var` at the top level becomes a property of `window`. ### The `let` Fix ```js for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // logs: 0, 1, 2 console.log(i); // ReferenceError (no leak) `` `let` is block-scoped, so `i` stays in the loop and each iteration gets a fresh binding. ### The IIFE Fix (Pre-ES6) ```js for (var i = 0; i < 3; i++) { (function (j) { setTimeout(() => console.log(j), 0); })(i); } // logs: 0, 1, 2 `` The IIFE creates a new function scope per iteration, capturing `i` as `j`. ### The Takeaway `var` leaks out of blocks, `if` statements, and loops because it is function-scoped. This causes namespace pollution, bugs, and the classic closure loop bug. `let` fixes all of this by being block-scoped. Avoid `var` in modern code.

Because var is function-scoped, not block-scoped. It ignores block boundaries (except function bodies). So a var inside an if is hoisted to the enclosing function or global scope. let and const are block-scoped and do not leak.

Because var is function-scoped. The loop variable exists in the enclosing function or global scope, not in the loop block. After the loop, the variable is still accessible. let is block-scoped and stays in the loop.

let is block-scoped and creates a fresh binding per iteration. Each callback closes over its own copy of i. With var, all callbacks share one i, which is the final value by the time they run.

With an IIFE (immediately invoked function expression) that created a new function scope per iteration, capturing the current value of i as a parameter. This was the pre-ES6 workaround.

Namespace pollution (variables linger after the block), bugs (accidentally reading or overwriting a finished block's variable), the classic closure loop bug, and accidental globals (var at the top level becomes a property of window).

Ready to master React completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.