Variables: let and const

JavaScript · Essentials · 8 min

Declarations decide where a name is visible and whether it can change, which shapes every line you write.

Modern JavaScript declares variables with two keywords:

  • const — the binding cannot be reassigned. Use it by default.
  • let — the binding can be reassigned. Use it when the value really changes, like a loop counter or an accumulator.

Both are block-scoped: a variable declared inside { ... } (an if, a loop, a bare block) does not exist outside it.

const makes the name constant, not the value. If a const holds an object or array, you can still change its contents — const list = []; list.push(1) is fine. Only list = [] is an error.

Accessing a let or const before its declaration line throws a ReferenceError; the region before the declaration is called the temporal dead zone. This catches ordering bugs early.

You will also meet var in older code. It is function-scoped rather than block-scoped, can be re-declared, and is readable (as undefined) before its declaration. Those properties cause subtle bugs, so don't use var in new code.

Names are case-sensitive, conventionally camelCase (userName), and may contain letters, digits, $ and _, but cannot start with a digit. UPPER_SNAKE_CASE is common for true module-level constants like MAX_RETRIES.

A variable declared but not assigned holds undefined. Declaring several at once (let a = 1, b = 2;) works, but one per line is easier to read.

Example

const greeting = "hello";
let count = 0;
count += 1;            // fine: let can be reassigned
// greeting = "bye";   // TypeError: Assignment to constant variable.

const user = { name: "Ada" };
user.name = "Grace";   // fine: the object is mutable
console.log(user);     // { name: 'Grace' }

if (true) {
  const inner = 42;
  let temp = inner * 2;
}
// console.log(inner); // ReferenceError: inner is not defined

let notYet;
console.log(notYet);   // undefined

Remember

  • Default to const; use let only when you reassign
  • let/const are block-scoped; var is function-scoped — avoid it
  • const prevents reassignment, not mutation of the object it points to

Watch out for

  • Thinking const arr = [] makes the array read-only — it only fixes the binding.

Check yourself

  1. const items = [1]; items.push(2); — what happens?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let