In JavaScript, variable declarations are fundamental, but choosing between var, let, and const can greatly impact code quality. Understanding when and why to use each helps create cleaner, more predictable code, essential for modern development.
var
and let
are both used to declare variables in JavaScript, but they have some key differences in how they handle scope, hoisting, and re-declaration.
Key Differences Between var
and let
-
Scope
-
var
is function-scoped: When you declare a variable withvar
, it’s accessible throughout the entire function in which it’s declared. -
let
is block-scoped: Variables declared withlet
are only accessible within the block (e.g.,{...}
) where they are defined, making it safer to use in most cases.
-
-
Hoisting
- Both
var
andlet
are hoisted to the top of their scope, butlet
is in a Temporal Dead Zone (TDZ) until the line where it’s defined, meaning you cannot access it before its declaration. -
var
, on the other hand, is hoisted without the TDZ, so it’s accessible throughout its scope (though it will beundefined
until its declaration).
- Both
-
Re-declaration
-
var
allows re-declaration of the same variable in the same scope, which can lead to unintended bugs. -
let
does not allow re-declaration in the same scope, helping avoid accidental overwrites.
-
Example 1: Scope Difference
function testVar() {
var x = 10;
if (true) {
var x = 20; // Same `x` in function scope, reassigns the outer `x`
console.log("Inside if-block:", x); // Output: 20
}
console.log("Outside if-block:", x); // Output: 20 (still the same `x`)
}
testVar();
With let
:
function testLet() {
let y = 10;
if (true) {
let y = 20; // New `y` scoped to this block only
console.log("Inside if-block:", y); // Output: 20
}
console.log("Outside if-block:", y); // Output: 10 (outer `y` is unchanged)
}
testLet();
In the testVar
function, var
declares a single x
for the entire function scope, so reassigning x
inside the if
block also changes it outside the block. With let
, y
inside the if
block is a separate variable from y
outside, preserving each y
's value in its own scope.
Example 2: Hoisting Difference
function hoistVar() {
console.log(x); // Output: undefined (due to hoisting)
var x = 10;
console.log(x); // Output: 10
}
hoistVar();
With let
:
function hoistLet() {
console.log(y); // Error: Cannot access 'y' before initialization
let y = 10;
console.log(y); // This line would not be reached
}
hoistLet();
In hoistVar
, var x
is hoisted to the top of the function scope, but it’s undefined
until the actual assignment. In hoistLet
, trying to access y
before it’s assigned results in a ReferenceError because let
variables are hoisted but remain in a Temporal Dead Zone (TDZ) until their declaration.
Example 3: Re-declaration
function redeclareVar() {
var x = 5;
var x = 10; // Allowed with `var`
console.log(x); // Output: 10
}
redeclareVar();
With let
:
function redeclareLet() {
let y = 5;
let y = 10; // Error: Identifier 'y' has already been declared
}
redeclareLet();
With var
, re-declaring x
in the same scope is allowed, which could cause unintended bugs. With let
, re-declaring y
in the same scope results in an error, helping to avoid accidental overwrites.
Summary
-
Scope:
var
is function-scoped;let
is block-scoped. -
Hoisting:
var
is hoisted without restriction, whilelet
is in a Temporal Dead Zone. -
Re-declaration:
var
allows it;let
does not.
In general, let
is recommended in modern JavaScript because it provides more predictable scoping and reduces the risk of unintended bugs.
Top comments (0)