JavaScript · Beginner

Variables in JavaScript: let, const and var

8 min readUpdated September 24, 2026Every example verified

In short: A variable is a named slot for a value. let declares one you can reassign, const one you cannot, and var is the older form with function-level scope and hoisting. Use const by default, let when the value must change, and avoid var in new code.

Names for values

A variable gives a value a name so later statements can use it. Declaring a variable creates the name; assigning gives it a value. JavaScript has three keywords for declaring, and the difference between them is the subject of this lesson.

let declares a variable whose value may change. const declares one whose name is bound to a value once and cannot be reassigned; it must be given a value on the same line. var is the original keyword from before 2015 and still works, but it behaves in two surprising ways described below, so new code uses let and const.

Both let and const are block scoped: a variable declared inside a pair of braces exists only until the closing brace. A loop counter declared with let in a for header is gone after the loop. var ignores blocks and is scoped to the whole function it sits in (or the whole program), so a var inside an if leaks out of it. var is also hoisted: the engine treats the declaration as if it were at the top of the function, with the value undefined until the assignment line runs. let and const are hoisted too, but reading them before their declaration line throws a ReferenceError instead of quietly giving undefined, which is the better behaviour.

The important subtlety of const is that it freezes the binding, not the value. A const holding an object or an array still lets you change the contents; you just cannot point the name at a different object. A variable declared with let but not assigned holds undefined.

Names may contain letters, digits, underscores and dollar signs, may not start with a digit, and are case sensitive. The convention is camelCase for ordinary names (totalPrice) and UPPER_SNAKE_CASE for true constants such as MAX_SEATS. Reserved words such as let, if and class cannot be names. Assigning to a name that was never declared is an error in strict mode, which is how programs run on this site.

Why prefer const? A reader who sees const knows the name means the same thing from that line to the end of its block and can stop tracking it. Reach for let only where a value genuinely changes: counters, accumulators, a result found by a loop.

Syntax

 JavaScript · syntax
let count = 0;          // declare and assign; may be reassigned
count = count + 1;      // reassignment: no keyword
let pending;            // declared, holds undefined

const rate = 0.2;       // must be assigned here; cannot be reassigned
const cart = [];        // the array itself can still change
cart.push("pear");      // allowed: the binding still points at the same array

var legacy = 1;         // function scoped, hoisted; avoid in new code

Declare each variable once, in the smallest block that needs it. A const with an object or array value can still have its contents modified.

let, const and var compared

letconstvar
Can be reassignedyesnoyes
Must be assigned when declarednoyesno
Scopeblockblockfunction
Read before its declaration lineReferenceErrorReferenceErrorundefined
Redeclare in the same scopeSyntaxErrorSyntaxErrorallowed
Use in new codewhen the value changesdefaultavoid

Declaring, reassigning and reading an unassigned variable

A ticket count changes, a venue name does not, and a seat is declared before it is known.

 JavaScript
let tickets = 3;
console.log("Tickets:", tickets);
tickets = tickets + 2;
console.log("After buying two more:", tickets);

const venue = "Old Mill Theatre";
console.log("Venue:", venue);

let seat;
console.log("Seat before assignment:", seat);
seat = "B12";
console.log("Seat after assignment:", seat);

Output

Tickets: 3
After buying two more: 5
Venue: Old Mill Theatre
Seat before assignment: undefined
Seat after assignment: B12

tickets = tickets + 2 reads the current value, adds two and stores the result back under the same name; only the first line needs the let keyword. venue never changes, so const documents that. seat is declared without a value and holds undefined, the value JavaScript uses for "nothing assigned yet", until the assignment on the next line.

Block scope: let stays inside its braces, var leaks out

The same name is declared with let both outside and inside a block; a var declared inside the block is visible after it.

 JavaScript
let area = "lobby";
if (true) {
  let area = "stage";
  var announced = "yes";
  console.log("Inside the block:", area);
}
console.log("After the block:", area);
console.log("var leaked out:", announced);

for (let i = 0; i < 3; i++) {
  // i exists only inside this loop
}
console.log("typeof i after the loop:", typeof i);

Output

Inside the block: stage
After the block: lobby
var leaked out: yes
typeof i after the loop: undefined

The inner let area is a separate variable that shadows the outer one only between the braces; once the block closes, area means the outer variable again. announced was declared with var, so it ignores the block and is still there afterwards. The loop counter i was declared with let in the loop header and no longer exists after the loop: typeof on a name that does not exist gives the string "undefined" rather than an error, which is why it is used here.

const protects the binding, not the contents

An order object and a price list declared with const are modified in place; reassigning the name fails.

 JavaScript
const order = { item: "espresso", qty: 1 };
order.qty = 2;
console.log(order);

const prices = [2.5, 3];
prices.push(4.25);
console.log(prices);

try {
  order = { item: "latte", qty: 1 };
} catch (err) {
  console.log("Error:", err.message);
}
console.log(order.item);

Output

{ item: 'espresso', qty: 2 }
[ 2.5, 3, 4.25 ]
Error: Assignment to constant variable.
espresso

Changing order.qty and pushing onto prices are both allowed because the names still refer to the same object and the same array. The line order = { ... } tries to point the name at a new object, which const forbids; the engine throws a TypeError whose message is shown. The try and catch wrapper only exists so the program can print the message and continue; the error handling lesson explains it. The last line confirms order still holds the original object.

Common mistakes

  • Using a let or const variable above its declaration

    Why it goes wrong: The name is in a "temporal dead zone" from the start of its block until the declaration line, and reading it there throws ReferenceError: Cannot access 'total' before initialization.

    Fix: Declare variables before the first line that uses them, ideally right where they are first needed.

     JavaScript · fix
    let total = 0;
    console.log(total);
  • Expecting const to make an object unchangeable

    Why it goes wrong: const only stops reassignment of the name. const settings = { dark: false }; settings.dark = true; is perfectly legal and changes the object.

    Fix: If you need a value that cannot be modified, call Object.freeze(settings) on it; const alone is not enough.

  • Declaring the same name twice in one scope

    Why it goes wrong: let count = 1; let count = 2; is a SyntaxError and the program does not start. Only var tolerates redeclaration, which is one reason it hides bugs.

    Fix: Declare once, then assign without a keyword: count = 2;.

  • Assigning to a name that was never declared

    Why it goes wrong: total = 5; with no let or const anywhere throws ReferenceError in strict mode. Outside strict mode it silently creates a global variable, which is worse because the mistake stays hidden.

    Fix: Always start a new variable with let or const. Programs on this site run in strict mode, so the error shows up immediately.

Where you use this

Almost every exercise keeps a running result while it reads input: a total, a count, the largest value seen so far. Those are the natural let variables, because the loop reassigns them. Everything else, such as the number of lines to read, a price per unit or a parsed input value, is declared with const, so anyone reading the program can tell at a glance which names carry state and which are fixed facts. When a lint tool complains that a let is never reassigned, change it to const.

 JavaScript · in practice
const n = Number(readline());
let total = 0;
for (let i = 0; i < n; i++) {
  const value = Number(readline());
  total += value;
}
console.log(total);

Key points

  • const by default; let when the value must change; no var in new code.
  • let and const live inside the nearest braces; var is scoped to the whole function.
  • A const object or array can still be modified; only the name is fixed.
  • Reading a let or const before its declaration line is a ReferenceError.
  • A declared but unassigned let holds undefined.
  • Names are case sensitive, use camelCase, and cannot start with a digit.

Try it yourself

The program crashes because it reassigns a const. Fix the declaration so it prints the balance after a withdrawal of 45, then add a deposit of 30 and print the balance again.

Your program
const balance = 120;
balance = balance - 45;
console.log(balance);
Expected output: 75 105

Practise this

Exercises for this lesson are in the JavaScript practice set.

Open the JavaScript playground

Frequently asked questions

Should I use let or const in JavaScript?

Use const unless the variable will be reassigned, then use let. Most variables in a typical program never change after their first assignment, so const ends up being the majority, and each let then signals to the reader that a value moves. Neither is faster than the other in practice; the choice is about clarity.

What is the difference between var and let?

var is scoped to the enclosing function and is hoisted with the value undefined, so it can be read before its declaration line and it leaks out of if blocks and loops. let is scoped to the enclosing block and throws if read before its declaration. let was added in ES2015 to fix exactly those two problems, which is why var is avoided in new code.

Does const make a value immutable?

No. const prevents the name from being pointed at another value, but if the value is an object or an array its contents can still be changed. To stop the contents changing as well, use Object.freeze(), which makes the object's own properties read-only (nested objects inside it are not frozen).

Progress is stored only in this browser.

How this page was checked. Every program on it was run with Node.js 22 at build time; runs in your browser in an isolated Web Worker by the publishing checks, and the output shown is what it printed. The Run buttons execute the same code on your device; nothing you type is sent anywhere.