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.