When to Use let vs const in Modern JavaScript

Use const by default and let only when the value needs to change. Learn the simple rule, see practical examples, and understand common patterns for both keywords.

5 min read

Choosing between let and const is one of the simplest decisions in JavaScript. There is a rule that makes it automatic: start with const, and switch to let only when you discover the value needs to change.

This rule is not just a style preference. It communicates intent clearly to anyone reading your code.

When another developer reads const, they immediately know the value stays the same. When they see let, they know to watch for reassignment.

Decision flow for choosing let or const

The decision flow is simple. Ask whether the variable gets reassigned after its initial value is set.

If no, use const. If yes, use let. That is the entire decision process, and once you internalize it, you will never hesitate between the two keywords again.

Use const by Default

const signals that a value is fixed for the lifetime of the variable. It protects against accidental reassignment and makes code easier to reason about because you know the variable always holds the same value once defined.

javascriptjavascript
const apiUrl = "https://api.example.com";
const maxRetries = 3;
const defaultConfig = { theme: "dark", language: "en" };

None of these values should change while the program runs. const enforces that at the language level. If you accidentally write apiUrl = "..." later, JavaScript throws an error instead of silently breaking every API call in your application.

const also works well for derived values that are computed once and never change after that initial computation:

javascriptjavascript
const basePrice = 100;
const taxRate = 0.08;
const finalPrice = basePrice * (1 + taxRate);
 
console.log(finalPrice);

The console prints 108. The variable finalPrice is computed from two other constants and never changes afterward. Marking it const confirms it is a one-time calculation, not a running total that updates.

For objects and arrays, const means the variable always points to the same container in memory. You can still modify the contents:

javascriptjavascript
const user = { name: "Alex", score: 0 };
 
user.score += 10;      // allowed: mutating the object
user.name = "Jordan";  // allowed: mutating the object
console.log(user);

The console prints { name: "Jordan", score: 10 }. The variable binding is constant but the object contents are not. This is useful because it prevents accidentally replacing the entire object while still allowing property updates.

Use let When the Value Changes

let is for variables that get reassigned after their initial value. The most common cases are counters, accumulators, and state that updates in response to user actions or incoming data.

javascriptjavascript
let attempts = 0;
attempts += 1;
attempts += 1;
console.log(attempts);

The console prints 2. Each line reads the current value, adds something to it, and stores the result back. This read-modify-write pattern requires let because the variable is being reassigned.

Loop counters are the classic let use case. The counter changes on every iteration, so const would throw an error:

javascriptjavascript
for (let i = 0; i < 5; i++) {
  console.log(i);
}

This prints 0 through 4, one per line. If you used const here, the i++ part would fail because const does not allow reassignment.

Accumulators that sum values or build up a result also need let. The total changes with each item in the loop:

javascriptjavascript
const prices = [10, 20, 30];
let total = 0;
 
for (const price of prices) {
  total += price;
}
 
console.log(total);

The console prints 60. Notice that price uses const inside the for...of loop. Each iteration creates a fresh binding for price, and that binding never reassigns within the loop body.

So const is correct for the loop variable even though the loop itself iterates.

Common Patterns

Here are the patterns you will use most often when deciding between let and const:

PatternKeywordExample
Fixed configuration valueconstconst TIMEOUT_MS = 5000
Loop counterletfor (let i = 0; ...)
Loop variable (for...of)constfor (const item of items)
Accumulator or running sumletlet sum = 0
DOM element referenceconstconst button = document.querySelector("button")
Fetch resultconstconst response = await fetch(url)
Toggle or boolean flagletlet isVisible = false
Function parameterno keyword neededfunction greet(name) {}

For loop variables in for...of and for...in, use const when the variable is not reassigned inside the loop body. Each iteration gets a fresh binding, so const works perfectly:

javascriptjavascript
const colors = ["red", "green", "blue"];
 
for (const color of colors) {
  console.log(color.toUpperCase());
}

The console prints RED, GREEN, and BLUE on separate lines. The variable color is a new const binding on each iteration, so it never needs to be reassigned.

When const Looks Wrong but Works

Some patterns look like they need let but actually work fine with const. Recognizing these saves you from weakening your variable declarations unnecessarily.

Array methods like map and filter return a new array. The original array is never reassigned, so const is correct:

javascriptjavascript
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);
 
console.log(doubled);

The console prints [2, 4, 6]. The variable numbers was never reassigned; the map method created a brand new array. The variable doubled is a separate const that also never changes.

Template literals that build a string once also work with const. Build the string, store it, and use it:

javascriptjavascript
const name = "Alex";
const role = "developer";
const greeting = `${name} works as a ${role}.`;
 
console.log(greeting);

The console prints "Alex works as a developer." The greeting is built once from two inputs and never changes.

Conditional values using a ternary also work with const. The variable is assigned once based on a condition, but it is never reassigned after that:

javascriptjavascript
const isLoggedIn = true;
const welcomeMessage = isLoggedIn ? "Welcome back!" : "Please sign in.";
 
console.log(welcomeMessage);

The console prints "Welcome back!" The variable welcomeMessage gets one value and keeps it.

If you find yourself trying to reassign a const and getting a TypeError, that is the signal to switch to let. But do not preemptively use let just in case the value might change later. Start with const and let the error guide you to the right choice when the need for reassignment becomes real.

For the broader comparison of all three keywords, see var vs let vs const. To understand the fundamentals, start with the JavaScript variables tutorial.

Rune AI

Rune AI

Key Insights

  • Use const by default for every variable declaration.
  • Switch to let only when you need to reassign the variable later.
  • const does not make objects or arrays immutable.
  • In for...of loops, use const when the loop variable is not reassigned.
  • Never use var in new code.
RunePowered by Rune AI

Frequently Asked Questions

Should I always use const?

Start with const for every variable. If you later need to reassign it, switch to let. This default makes your intent clear and prevents accidental reassignments.

Does const make objects immutable?

No. const prevents reassigning the variable to a different value, but you can still change properties inside a const object or push items into a const array.

What about loop variables like for loops?

Use let for loop counters because they change on every iteration. For for...of and for...in loops, use const when the loop variable does not reassign inside the body.

Conclusion

The rule is simple: start with const. If the value needs to change later, use let. This one decision makes your code safer, more readable, and easier to refactor. Every modern JavaScript codebase follows this pattern.