Skip to content

let and const

This lesson explains let and const with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.

ES6+ let and const Overview

ES6 introduced let and const as modern alternatives to var. Both are block-scoped, which makes variable behavior more predictable and helps prevent common bugs in loops, conditionals, and functions.

In modern JavaScript, const is the default choice for values that should not be reassigned, while let is used when a variable needs to change over time.

Keyword Description
let Block-scoped variable that can be reassigned
const Block-scoped variable that cannot be reassigned
Introduced In ES6 (ECMAScript 2015)
Scope Block scope
Hoisting Hoisted but not initialized until declaration
Modern Default Prefer const, use let when needed

Basic let and const Example

let count = 0;
const appName = "Dashboard";

count = 1;
count += 1;

console.log(count);
console.log(appName);

// appName = "Portal"; // Error

let allows reassignment, while const prevents reassigning the variable binding after initialization.

How let and const Work

Both keywords declare variables inside the nearest block such as { ... }, a loop, or a conditional. They are not accessible outside that block.

Step Description Example
Declare Variable Use let or const. const id = 1
Limit Scope Variable exists inside the block. if (...) { ... }
Reassign if Needed Only let can be reassigned. count++
Prevent Rebinding const keeps the binding fixed. const API_URL
Use Safely Avoid accidental global leakage. Cleaner modern code

Block Scope Example

if (true) {
  let message = "Inside block";
  const status = "active";

  console.log(message);
  console.log(status);
}

// console.log(message); // Error
// console.log(status);  // Error

Variables declared with let and const exist only inside the block where they are created.

let vs const

let score = 10;
const maxScore = 100;

score = 25;

console.log(score);
console.log(maxScore);

// maxScore = 200; // Error
Feature let const
Reassignment Allowed Not allowed
Must Initialize No Yes
Scope Block Block
Best For Counters, loops, changing values Constants, config, references

const with Objects and Arrays

const user = {
  name: "Alex",
  role: "admin"
};

const tags = ["js", "es6"];

user.role = "editor";
tags.push("modern-js");

console.log(user);
console.log(tags);

// user = {};   // Error
// tags = [];         // Error

const prevents reassigning the variable itself, but the contents of objects and arrays can still change. The reference stays the same.

let in Loops

for (let i = 0; i < 3; i += 1) {
  setTimeout(() => {
    console.log("let:", i);
  }, 100);
}

for (var j = 0; j < 3; j += 1) {
  setTimeout(() => {
    console.log("var:", j);
  }, 100);
}

let creates a new binding for each loop iteration, which avoids the classic var loop closure problem.

Using const for Constants

const API_URL =
  "https://api.example.com";

const MAX_ITEMS = 50;

const COLORS = {
  primary: "#2563eb",
  danger: "#dc2626"
};

console.log(API_URL);
console.log(MAX_ITEMS);
console.log(COLORS.primary);

Use const for values that should not be rebound, such as API URLs, limits, configuration objects, and shared references.

let and const vs var

Feature var let / const
Scope Function scope Block scope
Reassignment Allowed let yes, const no
Redeclaration Allowed in same scope Not allowed in same scope
Loop Behavior Can cause closure bugs Safer per-iteration bindings
Modern Usage Avoid in new code Preferred

No Redeclaration in the Same Scope

let value = 10;
// let value = 20; // Error

const title = "Dashboard";
// const title = "Portal"; // Error

{
  let value = 30;
  const title = "Nested";
  console.log(value, title);
}

You cannot declare the same variable name twice with let or const in the same scope. Inner blocks can declare their own separate bindings.

When to Use let vs const

  • Use const by default for most variables.
  • Use let for counters, accumulators, and reassigned values.
  • Use const for imported bindings, functions, and config objects.
  • Use let in loops when the index or value changes.
  • Avoid var in modern JavaScript projects.
  • Use clear names so reassignment needs are obvious.

Common let and const Use Cases

  • Declaring loop counters with let.
  • Storing API URLs and app constants with const.
  • Creating block-scoped temporary values in conditionals.
  • Preventing accidental reassignment of important references.
  • Writing safer asynchronous and event-driven code.
  • Using immutable-style patterns with const.
  • Replacing legacy var declarations in refactors.

let and const Best Practices

  • Default to const and switch to let only when reassignment is needed.
  • Keep variable scope as small as possible.
  • Use descriptive names such as userCount or apiUrl.
  • Do not use var in new code unless maintaining legacy scripts.
  • Initialize const values when declaring them.
  • Remember that const does not make objects deeply immutable.
  • Declare variables close to where they are used.

Common let and const Mistakes

  • Trying to reassign a const variable.
  • Assuming const makes object contents immutable.
  • Using var in loops with asynchronous callbacks.
  • Redeclaring the same variable in one scope.
  • Accessing variables before declaration in the temporal dead zone.
  • Using letconst would be clearer.
  • Creating unnecessarily large scopes for variables.

Key Takeaways

  • let and const are block-scoped ES6 variable declarations.
  • let can be reassigned; const cannot.
  • const should be your default choice in modern JavaScript.
  • Both are safer and more predictable than var.
  • Block scope and the temporal dead zone are covered in the next lessons.

Pro Tip

Start with const for every new variable. If the code later needs reassignment, change it to let.