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
-
varis function-scoped: When you declare a variable withvar, it’s accessible throughout the entire function in which it’s declared. -
letis block-scoped: Variables declared withletare only accessible within the block (e.g.,{...}) where they are defined, making it safer to use in most cases.
-
-
Hoisting
- Both
varandletare hoisted to the top of their scope, butletis 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 beundefineduntil its declaration).
- Both
-
Re-declaration
-
varallows re-declaration of the same variable in the same scope, which can lead to unintended bugs. -
letdoes 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:
varis function-scoped;letis block-scoped. -
Hoisting:
varis hoisted without restriction, whileletis in a Temporal Dead Zone. -
Re-declaration:
varallows it;letdoes 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)