Understanding var, let, and const in JavaScript

When working with JavaScript, understanding variable declarations is crucial. JavaScript provides three ways to declare variables: var, let, and const. Each has unique characteristics regarding scope, hoisting, and mutability. Let's explore them in detail.


1. var (Function Scoped, Hoisted, Can be Re-declared)

Characteristics:

  • Function Scoped: Variables declared with var are function-scoped, meaning they are accessible only within the function where they are declared.

  • Hoisting: var declarations are hoisted, meaning they are moved to the top of their scope and initialized as undefined.

  • Can be Re-declared: A var variable can be declared multiple times within the same scope without errors.

  • Can be Updated: The value of a var variable can be changed after initialization.

Example:

function testVar() {
    console.log(a); // Undefined (Hoisting)
    var a = 10;
    console.log(a); // 10

    var a = 20; // Redeclaration allowed
    console.log(a); // 20
}
testVar();

Issues with var:

  • Lack of block scope: Variables defined with var inside a block {} are accessible outside of it.
if (true) {
    var x = 100;
}
console.log(x); // 100 (Accessible outside block)

2. let (Block Scoped, Hoisted but Not Initialized, Cannot be Re-declared in the Same Scope)

Characteristics:

  • Block Scoped: Variables declared with let are limited to the block {} where they are defined.

  • Hoisting: let is hoisted, but it is not initialized, leading to a Temporal Dead Zone (TDZ) until assignment.

  • Cannot be Re-declared in the Same Scope: Unlike var, redeclaration of let in the same scope results in an error.

  • Can be Updated: Values assigned to let variables can be changed.

Example:

function testLet() {
    // console.log(b); // Error: Cannot access 'b' before initialization
    let b = 30;
    console.log(b); // 30

    b = 40; // Allowed
    console.log(b); // 40
}
testLet();

Block Scope Behavior:

if (true) {
    let y = 50;
    console.log(y); // 50 (Accessible inside the block)
}
// console.log(y); // Error: y is not defined (Block scoped)

3. const (Block Scoped, Hoisted but Not Initialized, Cannot be Re-assigned or Re-declared)

Characteristics:

  • Block Scoped: Like let, const is block-scoped.

  • Hoisting: const is hoisted but not initialized, leading to a Temporal Dead Zone (TDZ) before assignment.

  • Cannot be Re-declared: Once assigned, a const variable cannot be re-declared in the same scope.

  • Cannot be Re-assigned: A const variable must be initialized at declaration and cannot be reassigned.

Example:

const c = 100;
console.log(c); // 100

// c = 200; // Error: Assignment to constant variable

Block Scope Behavior:

if (true) {
    const z = 300;
    console.log(z); // 300
}
// console.log(z); // Error: z is not defined

Objects and Arrays with const

Although const variables cannot be reassigned, their properties can be modified.

const person = { name: "Alice" };
person.name = "Bob"; // Allowed
console.log(person.name); // Bob

// person = { name: "Charlie" }; // Error: Assignment to constant variable

Key Differences Between var, let, and const

Featurevarletconst
ScopeFunction ScopeBlock ScopeBlock Scope
HoistingHoisted (initialized to undefined)Hoisted (but not initialized)Hoisted (but not initialized)
RedeclarationAllowedNot AllowedNot Allowed
ReassignmentAllowedAllowedNot Allowed
Temporal Dead ZoneNoYesYes

Scope in JavaScript: Function Scope vs. Block Scope

Function Scope

  • A variable is accessible throughout the function where it is declared.

  • var is function-scoped, meaning it is confined within the function but not within block {}.

function example() {
    var x = 10;
    if (true) {
        var y = 20;
    }
    console.log(y); // 20 (Still accessible)
}
example();
// console.log(x); // Error: x is not defined outside the function

Block Scope

  • A variable is only accessible inside the block {} where it is declared.

  • let and const are block-scoped.

if (true) {
    let a = 50;
    const b = 60;
    console.log(a, b); // 50 60
}
// console.log(a, b); // Error: a and b are not defined outside the block

When to Use var, let, and const?

  • Use var only if supporting older JavaScript versions (ES5 and earlier). Otherwise, avoid it due to scoping issues.

  • Use let when you need a variable whose value will change.

  • Use const for variables that should not be reassigned (e.g., constants, objects, arrays that should not be re-assigned).


Conclusion

Understanding the differences between var, let, and const is essential for writing clean and bug-free JavaScript code.

  • Prefer const by default.

  • Use let if you need to modify the variable.

  • Avoid var unless necessary for legacy support.

By following these best practices, you ensure better code maintainability and fewer unexpected behaviors in JavaScript applications!