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 constMake variables, and know when a name can get a new value.
- 02Tell a new value from a change insideExplain why a
constarray can still get new items. - 03Spot the problems with varKnow how
varleaks out of blocks, exists before its line runs, allows the same name twice, and adds towindow.
Watch the video lectures
Full course on YouTube (opens in a new tab) ↗- Lecture 6Variables: var, let, and constWatch on YouTube (opens in a new tab) ↗
- Lecture 9How variables really work, in depthWatch on YouTube (opens in a new tab) ↗
A variable is a name for a value
A variable is a name for a value. A value is one piece of data, like the number 0 or the text "Asha". When you write let score = 0;, JavaScript makes a variable named score and puts the number 0 in it. Later, your code can use the name score to get the number back.
let score = 0; makes a box named score and puts the value 0 in it. Later, your code uses the name to get the value back.You saw a small version of this in the Why JavaScript? lesson. A Like button kept its count in a variable called likes. It used = to store each new count, and console.log to print messages. This lesson goes through the same idea slowly, one rule at a time.
Use const for most variables. Use let when the same name needs a new value later. Don't use var in new code.
const userName = "Asha";
let teaCount = 1;
teaCount = teaCount + 1;
console.log(userName);
console.log(teaCount);Line 1 uses const to make a variable named userName. It holds the text "Asha", and it will keep that value. Line 2 uses let to make a counter, teaCount, and starts it at 1. Line 3 works out teaCount + 1, which is 2, and puts 2 into teaCount. Lines 4 and 5 print Asha and 2.
Picture a shelf full of boxes. Each box has a label, like "score". You don't need to describe what is inside each time. You just say the label, and everyone knows which box you mean.
- In real life: The 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 to find the box
- In JavaScript: Using the variable's name in your code
- In real life: Taking the old thing out and putting a new thing in
- In JavaScript: Giving a
letvariable a new value
Making a variable is called declaring it. You declare a variable with a keyword: a word that has a special job in JavaScript. This lesson covers three of these keywords:
letandconstare the modern ones. You will use them every day.varis the old one. You need to be able to read it in older code, but you should almost never write it.
let and const: can the name get a new value?
STEP THROUGHTo declare a variable, you pick a keyword and then a name. You can give it its first value on the same line. Giving a variable its first value is called initializing it.
const appName = "CompleteFrontend";makes a name that keeps the same value.let score = 0;makes a name that can get a new value later.
Giving a variable that already exists a new value is called reassignment. You do it with the = sign. Read a line with = from right to left:
- First, JavaScript works out the right side.
- Then it puts the result into the name on the left.
let message;
console.log(message);
message = "Ready";
console.log(message);Line 1 makes message but gives it no value. So it starts as undefined, which is JavaScript's way of saying "no value yet". Line 2 prints undefined. Line 3 puts the text "Ready" into message, and line 4 prints Ready. A const must get its value on the same line, because it can never get one later.
Guess the value printed on line 4. Step through the let version, then switch to const and see where the real error happens.
script
score = 10;score = score + 5;console.log(score);Step through the let version first. score starts at 0, then becomes 10, then becomes 15. Now switch to const. Line 1 still works. Line 2 throws a real TypeError, because a const name can't get a new value. An error is JavaScript's way of saying "I can't do this". It stops the program. A TypeError is one kind of error.
score = 10;, in both. With let, the box gets the new value. With const, JavaScript throws a TypeError, and score keeps 0.If a const gets a new value, JavaScript throws this error. It means one of two things. Maybe the variable should have been made with let. Or maybe your code is changing a value by mistake, when that value should stay the same.
A new value vs a change inside
INTERACTIVESome values hold other values inside them:
- An array is a list of values, like
["pen", "book"]. - An object holds values that each have a name, like
{ theme: "dark" }.
With arrays and objects, const surprises many people. That's because there are two different ways to change things:
- Reassignment gives the name a whole new value, like
cart = ["book"].constblocks this. - Mutation changes what is inside the value the name already has, like
cart.push("book").constallows this.pushadds an item to the end of an array.
So const keeps the name on the same array or object. It does not lock what is inside.
Imagine a label glued to a toolbox. You can't peel it off and stick it on another toolbox. But you can still open the toolbox and move the tools around inside.
- In real life: A label glued to one toolbox
- In JavaScript: A
constname that stays on one array or object - In real life: Moving the label to a new toolbox
- In JavaScript: Reassignment, which
constblocks - In real life: Putting a screwdriver in the same toolbox
- In JavaScript: Mutation, like
cart.push("book") - In real life: Two labels on the same toolbox
- In JavaScript: Two variables for one array
In the next replay, you choose what line 2 does. It can add an item to the array with push. Or it can try to give cart a whole new array. Guess which one const allows before you press Step.
Guess whether const allows line 2. Step through mutation first, then switch to reassignment.
script
cart.push("book");console.log(cart);const other = cart;other.push("ink");console.log(cart);const cart = ["pen"];. Adding an item changes what is inside the same array, so const allows it. Giving cart a whole new array is not allowed.const settings = { theme: "dark" };
settings.theme = "light";
console.log(settings.theme);The name settings stays on one object the whole time. Line 2 changes the theme value inside that object, so line 3 prints light. That is mutation, so const allows it. Giving settings a whole new object would be reassignment, and const would block it.
One more thing happens in the replay. Line 4, const other = cart;, does not copy the array. It gives the same array a second name. So when line 5 runs other.push("ink"), cart shows the ink too.
const other = cart; doesn't make a copy. It ties a second name to the same array. So the ink added through other shows up in cart too.Rules for names, and words you can't use
SORTERA variable's name is also called an identifier. A name can use:
- letters, including letters like
é, socaféis a real JavaScript name - digits, but not as the first character
- the signs
$and_
A name can't have a space or a hyphen (-) in it.
const userName = "Ada";const firstName2 = "Grace";const $price = 20;const _count = 3;const café = "coffee";console.log(userName, firstName2, $price, _count, café);const userName = "Asha";
const username = "Lin";
console.log(userName);
console.log(username);userName and username differ by one capital letter. To JavaScript, they are two different names. So the example prints Asha and then Lin. Write each name the same way every time. If you change one capital letter, JavaScript looks for a different variable.
Allowed doesn't always mean good. $price is allowed, but many teams keep $ for special uses by their tools. In Stage 1 you met camelCase: words joined together, with a capital letter at the start of each new word. Use clear camelCase names like firstName, uploadCount, and totalAmount.
userName2fast$price_countmy-nameclasscaféfirstName2total amount
Put each name in a group: allowed or not allowed. If you pick the wrong group, you'll see which rule the name breaks.
Words like let, const, var, class, return, function, and if already have a job in JavaScript. They are called reserved words, and you can't use them as names. Pick a name that says more instead, like lessonClass instead of class.
Why new code doesn't use var
COMPAREvar is part of JavaScript, and older code uses it a lot. It can store values just fine. The problem is its rules. A block is the code between a pair of curly braces { }, like the body of an if. let and const stay inside their block. var doesn't, so its rules don't match the braces you see.
A modern label stays in the drawer section where you put it. An old sticky note can slide past the divider into the next section. It can show up before you write on it. And you can stick a second note with the same name over the first one.
- In real life: A sticky note that slides past the drawer divider
- In JavaScript:
vardoesn't stay inside its block - In real life: A blank note that is there before you write on it
- In JavaScript:
varexists asundefinedbefore its line runs - In real life: A second note stuck over the first one
- In JavaScript:
varlets you declare the same name twice
The table compares the three keywords. Each row asks one question. Each column gives the answer for one keyword.
| What you want to know | const | let | var |
|---|---|---|---|
| Should you use it in new code? | Yes. Use it first, for names that never get a new value. | Yes, for names that need a new value later. | No. Leave it in old code. |
| Can the name get a new value? | No. It throws a TypeError. | Yes. | Yes. |
| Can the inside of its array or object change? | Yes. | Yes. | Yes. |
| Where can you use the name? | Only inside its block { }. | Only inside its block { }. | In the whole function or script, even outside the block. |
| Can you declare the same name twice in one place? | No. It's a SyntaxError. | No. It's a SyntaxError. | Yes. |
| What if you read it before its line runs? | It throws a ReferenceError. | It throws a ReferenceError. | You get undefined. |
In a classic script, does a top-level one become part of window? | No. | No. | Yes. |
Here are the traps one by one. Each var example comes with a matching let example, and each shows the real result.
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);- A
varmade inside anifblock can still be used after the block ends. Theletversion throws aReferenceErrorafter the block. AReferenceErrormeans JavaScript can't find that name. - Reading a
varbefore its line runs printsundefined. That's because JavaScript makes everyvarname early, before the code runs, and gives itundefined. This is called hoisting. Reading aletbefore its line runs throws aReferenceErrorinstead. The time before the line runs is called the temporal dead zone. varlets you declare the same name twice in one place.letandconstdon't. They throw aSyntaxError, which means the code is written in a way JavaScript doesn't accept.
Don't swap every var for const without checking. First, look for names that get a new value later, and use let for those. Then run the code or its tests to check that it still works. A later lesson on scope covers the few old patterns that need more care.
var oldGlobal = "window property";let modernGlobal = "not a window property";console.log(window.oldGlobal);console.log(window.modernGlobal);A classic script is a plain <script> tag on a web page. window is the object that stands for the browser page. In a classic script, a var at the top level, outside every function and block, also becomes a property of window. So line 3 prints window property. A top-level let or const doesn't do this, so line 4 prints undefined. Modules, a newer kind of script file, have their own rules. Either way, the advice is the same: don't write var in new code.
Scope means the part of your code where a name can be used. Scope, hoisting, and the temporal dead zone each get a full lesson in Stage 4. The Closures lesson shows why old loops written with var caused famous bugs.
Where you will use variables
TRY ITReal apps use variables to keep track of things. Variables give names to the parts that change or matter, like:
- counters, like the number of photos uploaded
- settings, like a light or dark theme
- messages to show the user
- the item a user picked
- results you work out on the way, which make long code easier to read
Further down, a playground lets you change the number of tea packs in a cart. In it, price stays the same, so it is a const. total gets a new value after the multiplication, so it is a let. A running total in a checkout, or a counter on a page, works the same way.
const quantityText = "2";
const price = 3;
console.log(typeof quantityText);
const total = Number(quantityText) * price;
console.log(total);A form field is a box on a web page where the user types, like a quantity box. The browser gives you what was typed as text, even in a box made for numbers. Line 1 stands in for that: the quantity is the text "2". Line 3 uses typeof, which tells you what kind of value something is. It prints string, JavaScript's word for text. Line 4 uses Number(quantityText) to turn the text into the number 2, then multiplies it by the price. Line 5 prints 6. The Numbers lesson explains this kind of change in more detail.
const price = 3;const quantity = 2;let total = price;total = total * quantity;console.log(total);price stays 3 because it is a const. total starts as the price. Then line 4 gives total a new value, 6. That is why total is a let.
const appName = "PhotoBox";let uploadCount = 0; uploadCount = uploadCount + 1; const settings = { theme: "dark" };settings.theme = "light"; console.log(appName, uploadCount, settings.theme);appName never changes, so it is a const. uploadCount goes up each time the user uploads a photo, so it is a let. settings stays the same object the whole time, so it can be a const, even though the theme inside it changes.
When you check your own code, every let needs a reason. If a name never gets a new value, make it a const.
Common mix-ups
“const means the value can never change.”
Not quite. const only means the name can't get a new value. If the value is an object or an array, what is inside it can still change.
“= checks whether two values are equal.”
No. = puts a value into a variable. To check whether two values are equal, you use other signs. The course covers them later.
“var is just an older spelling for let.”
No. var has different rules. It doesn't stay inside blocks, only inside functions. It exists as undefined before its line runs. It lets you declare the same name twice. And in a classic script, a top-level var becomes a property of window.
“A name that is allowed is always a good name.”
Not always. $x and café are allowed. But a good name also tells other people what the value is for.
“Two variables always mean two separate values.”
Not always. Two variables can lead to the same object or array. A change made through one name shows up through the other name too.
Practice exercises
5 EXERCISESTry each task before you open the hints. The answer check doesn't mind capital letters or extra spaces. JavaScript itself is stricter, so the code has to be exactly right.
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 line prints 5. The push adds a second item to the const array. That is mutation, which const allows. So wallet.length prints 2.
This program throws an error. Change one word to fix it. Which word do you use?
const total = 0;
total = total + 5;
console.log(total);let total = 0;
total = total + 5;
console.log(total);total gets a new value on line 2, so it must be made with let. Now the program prints 5 instead of throwing a TypeError.
A photo app has three variables. appName is the app's name and never changes. uploadCount goes up by 1 after each upload. settings is an object, and the theme inside it changes from dark to light. Pick a keyword for each one. 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 never changes, so use const. uploadCount gets a new value, so use let. settings stays the same object the whole time, so it can be const, even though settings.theme changes.
Fix these names so JavaScript allows them, but keep what they mean: 2fast, total amount, and class.
const fastCar = true;
const totalAmount = 42;
const lessonClass = "variables";
console.log(fastCar, totalAmount, lessonClass);fastCar no longer starts with a digit. totalAmount joins the two words with camelCase instead of a space. lessonClass avoids the reserved word class.
Guess what the buggy program prints. Then look at the fixed version, where the value inside the block stays 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 the var inside the block leaks out. The fixed program uses let, so the status inside the block is a separate variable from the status outside. It prints draft inside the block and published after it.
Quiz: check your understanding
8 QUESTIONSYour first try counts. Every answer explains why it is right or wrong. For code questions, go through the code line by line before you choose.
Question 1 of 8Which keyword should you use first, for a variable that will never get a new value?
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 (a change inside the array) rather than reassignment (a new value for the name)?
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 variable name is not allowed?
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 doesn't new JavaScript code use var?
Choose an answer to see the explanation.
Question 8 of 8Which rule is best?
Choose an answer to see the explanation.
Key takeaways
- A variable is a name for a value.
conststops the name from getting a new value. It does not lock what is inside an object or array.- Use
letfor names that need a new value later, like counters and running totals. - Names can use letters,
$,_, and digits after the first character. They can't have spaces or hyphens, start with a digit, or be a reserved word. - Don't use
varin new code. It leaks out of blocks, exists before its line runs, allows the same name twice, and can add towindow.
Remember the one-liner.
A variable is a name for a value. Use const first, use let when the name needs a new value, and leave var in old code.
Up next: Data types. You'll meet the kinds of values a variable can hold.