Variables: let, const & var
Learn how JavaScript stores values with let and const, why mutation is different from reassignment, how to choose legal names, and why new code avoids var.
- 01Choose let or constDeclare values clearly and know when reassignment is allowed.
- 02Tell reassignment from mutationPredict why a const array can change without being reassigned.
- 03Avoid var safelyRecognize block scope, hoisting, redeclaration, and global-object traps.
Variables name the values your program keeps
A variable is a name for a value. When you write let score = 0;, JavaScript creates the name score and stores the number 0 in it. Later, your program can read score instead of remembering where the number came from.
You already met a tiny version in Why JavaScript?: a Like button kept a likes count, used = to store new values, and printed messages with console.log. This lesson slows down that idea until each rule is predictable.
Use const by default, use let when the same name must be assigned a new value, and avoid var in new code.
Imagine a shelf full of boxes. A label that says “score” means you do not need to describe the contents every time. You point at the label, and everyone knows which value you mean.
- In real life: A label on a box
- In JavaScript: The variable name, such as
score - In real life: The thing inside the box
- In JavaScript: The value, such as
0or"Ada" - In real life: Reading the label later
- In JavaScript: Using the variable in an expression
- In real life: Moving a removable label
- In JavaScript: Reassigning a
letvariable
Where the analogy stops: Real boxes usually hold separate physical things. JavaScript objects and arrays can have two labels pointing at the same value, so the box picture needs an upgrade in the mutation section.
There are three declaration keywords in this lesson: let, const, and var. The first two are modern and should feel natural by the end. The third is older; you must read it when you meet older code, but you should almost never write it.
let and const: changing the label
STEP THROUGHDeclaring a variable has two parts: choose the keyword, then choose the name. Initializing it adds the first value.
const appName = "CompleteFrontend";creates a name that should keep pointing at the same value.let score = 0;creates a name that may be reassigned later.
Reassignment means giving an existing variable name a new value. Read an assignment from right to left: work out the expression on the right, then store the result in the name on the left.
Predict the value beside line 4. Step through the let version, then switch to const and notice where the real error happens.
script
score = 10;score = score + 5;console.log(score);In the let version, score starts at 0, becomes 10, then becomes 15. In the const version, line 1 is fine and line 2 throws a real TypeError: the name is already fixed to its first value.
A const reassignment error usually means one of two things: either the value should have been declared with let, or your code is accidentally trying to overwrite a value that should stay stable.
Reassignment is not mutation
INTERACTIVEThe most common const surprise appears with arrays and objects. const protects the variable name from pointing at a different value. It does not freeze every piece inside the value.
If a label is glued to a toolbox, you cannot peel it off and stick it on a different toolbox. But you can still open that toolbox and rearrange the tools inside.
- In real life: A label glued to one toolbox
- In JavaScript: A
constname fixed to one array or object - In real life: Moving the glued label to a new toolbox
- In JavaScript: Reassignment, which
constblocks - In real life: Adding a screwdriver to the same toolbox
- In JavaScript: Mutation, like
cart.push("book") - In real life: Two labels on the same toolbox
- In JavaScript: Two variables referencing one array
Where the analogy stops: JavaScript values are not literally boxes. The key idea is identity: an object or array can stay the same value while its contents change.
In the next replay, line 2 can either mutate the array with push or try to reassign cart to a brand-new array. Predict which one const allows.
Predict whether const blocks each line. Step through mutation first, then switch to reassignment.
script
cart.push("book");console.log(cart);const other = cart;other.push("ink");console.log(cart);Notice the bonus twist: const other = cart; does not copy the array. It makes a second label for the same array. When other.push("ink") runs, cart shows the ink too.
Naming rules and reserved words
SORTERJavaScript variable names are formally called identifiers. A legal identifier can contain letters, digits after the first character, $, and _. Many Unicode letters are allowed too, so café is legal JavaScript.
const userName = "Ada";const firstName2 = "Grace";const $price = 20;const _count = 3;const café = "coffee";console.log(userName, firstName2, $price, _count, café);Legal does not always mean good style. $price is legal, but many teams reserve $ for framework conventions. Stage 1 introduced camelCase, so prefer names like firstName, uploadCount, and totalAmount.
userName2fast$price_countmy-nameclasscaféfirstName2total amount
Sort each proposed name. A wrong answer explains which rule it breaks.
Words such as let, const, var, class, return, function, and if already have jobs in JavaScript grammar. Use a descriptive variation such as lessonClass instead of class.
Why modern JavaScript avoids var
COMPAREvar is part of JavaScript, and older code uses it everywhere. The problem is not that var cannot store values. It can. The problem is that its rules do not match the braces you see on the page.
A modern label stays in the drawer section where you put it. An old sticky note can slide past the divider, show up too early, and cover an earlier note with the same name.
- In real life: A sticky note that ignores drawer dividers
- In JavaScript:
varignores block scope - In real life: A faint note visible before you write the final text
- In JavaScript:
varis hoisted asundefined - In real life: Putting a second sticky note over the first
- In JavaScript:
varallows redeclaration
Where the analogy stops: The analogy is only about surprising visibility. Real sticky notes do not have JavaScript's precise function scope or global-object behavior.
| Question | const | let | var |
|---|---|---|---|
| Best new-code default | Yes, when the name will not be reassigned | Yes, when the value must change | No |
| Can be reassigned? | No | Yes | Yes |
| Can an object/array it points at mutate? | Yes | Yes | Yes |
| Scope you should think about here | Block scoped | Block scoped | Function scoped |
| Redeclare in the same scope? | No | No | Yes |
| Read before declaration? | ReferenceError before initialization | ReferenceError before initialization | undefined |
| Top-level classic script creates window property? | No | No | Yes |
Here are the specific traps, each with the real outcome shown.
if (true) { var mood = "visible outside";}console.log(mood);if (true) { let mood = "hidden outside";}console.log(mood);console.log(score);var score = 5;console.log(score);let score = 5;var count = 1;var count = 2;console.log(count);let count = 1;let count = 2;console.log(count);varinside anifblock leaks outside that block; the matchingletexample throws a ReferenceError after the block.- Reading
var scorebefore its assignment printsundefined; readinglet scorebefore its declaration throws because it is not initialized yet. varallows redeclaration in one scope;letandconstcatch that duplicate as a SyntaxError.
var oldGlobal = "window property";let modernGlobal = "not a window property";console.log(window.oldGlobal);console.log(window.modernGlobal);In a classic browser script, top-level var also creates a property on window. Top-level let and const do not. Modern modules have different top-level rules, but the everyday guidance is unchanged: do not write new var.
Scope, hoisting, and the temporal dead zone all get deeper lessons in Stage 4. If loops with callbacks already sound mysterious, the published Closures lesson shows why old var loops caused famous bugs.
Where you will use variables
Variables are not just a syntax exercise. They let you name the moving pieces in an application: counters, settings, messages, selected items, and temporary results that make longer code readable.
const appName = "PhotoBox";let uploadCount = 0; uploadCount = uploadCount + 1; const settings = { theme: "dark" };settings.theme = "light"; console.log(appName, uploadCount, settings.theme);appName is a stable label, so it is const. uploadCount changes as work happens, so it is let. settings stays pointed at one object, so it can be const even though a property changes.
When you review your own code, every let should have a reason. If you never assign that name again, make it const.
Common misconceptions
“const means the value can never change.”
const means the variable name cannot be reassigned. If the value is an object or array, its contents may still mutate.
“= checks whether two values are equal.”
= stores a value. Equality checks use comparison operators, which the course covers later.
“var is just an older spelling for let.”
var is function scoped, hoisted as undefined, permits redeclaration, and can create global properties in classic scripts. Those are different rules.
“A valid name is automatically a good name.”
$x and café can be valid, but a good name also explains the value's job to other readers.
“Two variables always mean two separate values.”
Two variables can point at the same object or array. Mutating through one name can be visible through the other.
Practice: declare, assign, repair
5 EXERCISESTry each task before opening the hints. The answer check is forgiving about case and extra spaces, but the JavaScript rules are not.
What two values does this program print?
let coins = 1;
coins = coins + 4;
const wallet = ["card"];
wallet.push("receipt");
console.log(coins);
console.log(wallet.length);coins becomes 5, so the first log prints 5. The const array is mutated by push, so it contains two items and wallet.length prints 2.
Which one-word keyword change fixes this program?
const total = 0;
total = total + 5;
console.log(total);let total = 0;
total = total + 5;
console.log(total);total is intentionally reassigned, so it must be declared with let. Now the program prints 5 instead of throwing a TypeError.
Pick declarations for appName, uploadCount, and settings. Type the three keywords in order.
const appName = "PhotoBox";
let uploadCount = 0;
uploadCount = uploadCount + 1;
const settings = { theme: "dark" };
settings.theme = "light";
console.log(appName, uploadCount, settings.theme);appName is stable, so use const. uploadCount is assigned again, so use let. settings keeps pointing at the same object, so it can be const even though settings.theme changes.
Repair these names without changing their meaning: 2fast, total amount, and class.
const fastCar = true;
const totalAmount = 42;
const lessonClass = "variables";
console.log(fastCar, totalAmount, lessonClass);fastCar moves the digit problem into a word, totalAmount removes the space with camelCase, and lessonClass avoids the reserved word class.
Predict what the buggy program prints. Then compare it with the solution that keeps the inner value inside the block.
if (true) {
var status = "draft";
}
console.log(status);let status = "published";
if (true) {
let status = "draft";
console.log(status);
}
console.log(status);The buggy program prints draft because var leaks out of the block. The solution uses block-scoped let names: the inner draft status is separate from the outer published status.
Quiz: check your understanding
8 QUESTIONSYour first try counts, but every answer explains the rule. For code questions, trace each line before choosing.
Question 1 of 8What should you use by default for a variable that will not be reassigned?
Choose an answer to see the explanation.
Question 2 of 8What does this program print?
Read the code, then predictlet score = 0; score = 10; score = score + 5; console.log(score);Choose an answer to see the explanation.
Question 3 of 8Which line is mutation rather than reassignment?
Read the code, then predictconst cart = ["pen"]; cart.push("book");Choose an answer to see the explanation.
Question 4 of 8What happens here?
Read the code, then predictconst total = 0; total = 1;Choose an answer to see the explanation.
Question 5 of 8Which identifier is invalid?
Choose an answer to see the explanation.
Question 6 of 8What does this var program print?
Read the code, then predictconsole.log(score); var score = 5;Choose an answer to see the explanation.
Question 7 of 8Why does new JavaScript avoid var?
Choose an answer to see the explanation.
Question 8 of 8Which rule of thumb is best?
Choose an answer to see the explanation.
Key takeaways
- A variable is a name that stores or refers to a value.
constprevents reassignment of the name. It does not freeze object or array contents.letis for names you intentionally assign again, such as counters and running totals.- Legal names can use letters, later digits,
$,_, and many Unicode letters, but not spaces, hyphens, starting digits, or reserved words. - Avoid
varin new code because its scope, hoisting, redeclaration, and global behavior are surprising.
Remember the one-liner.
A variable is a name for a value; default to const, use let for reassignment, and leave var in the past.
Up next: Data types, where you will meet the kinds of values your variables can hold.