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); // undefinedRemember
- Default to
const; useletonly when you reassign let/constare block-scoped;varis function-scoped — avoid itconstprevents 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.