Names: let, const and the block they live in
Two ways to declare a name, the braces that bound it, and why a `const` object can still change under you.
A variable is a name attached to a value, so you can refer to the value later without writing it out again. Attaching the name is a declaration, and JavaScript has two words for it that you should use, and one you should not.
Add count = count * 10; before the console.log and predict the number.
let count = 1; declares the name and gives it a value. The second line has no let, because the name already exists; it is an assignment, and the = means "put this value in that name", not "these are equal".
Now the other word. This one is meant to fail, so read the message rather than the number.
It prints 10, then stops with TypeError: Assignment to constant variable. Change const to let and run it again.
const declares a name that cannot be pointed at anything else afterwards. It must be given a value on the same line, because there will never be another chance. The refusal happens while the program runs, not before it starts, which is why the 10 was printed first.
The standard advice, which this course follows, is to use const for everything and switch to let only when you find yourself needing to reassign. A reader then knows from the first word of the line whether the name will move.
The block is the boundary
Delete the let from the inner declaration and run it again. One number changes.
Two names spelled the same, holding different values, and the outer one is unharmed. The region of a program where a name can be used is its scope, and a name declared with let or const is scoped to the nearest enclosing pair of braces.
An inner declaration of the same name shadows the outer one: inside the block, the name refers to the inner value, and the outer value is untouched and comes back at the closing brace.
When you deleted the inner let, there was no second name. The line assigned to the outer x, and both messages printed 2.
Declaring twice
Within one block, a name may be declared once. Assigning to it again is normal; declaring it again is not.
let total = 1;
let total = 2;
// SyntaxError: Identifier 'total' has already been declaredNotice when that happens. It is not a TypeError thrown when the second line runs; it is a SyntaxError raised while the file is being read, so nothing at all executes, not even a console.log on line one. Duplicate declarations are caught by looking at the text, without running it.
The one you will inherit: var
Before 2015 there was only var, and you will read a great deal of code that uses it. It is scoped to the whole enclosing function rather than to a block.
Change var leaks to let leaks and run it again. Read the error and match it to the line that broke.
leaks was declared inside the braces and is still readable outside them, because var does not see braces at all; only a function boundary stops it. stays behaves the way you would expect and is gone at the closing brace.
var can also be redeclared as often as you like without complaint, which turns the duplicate-name SyntaxError above into silence. There is no reason to write var in new code. There is every reason to recognise it.
const does not freeze the value
This is the point of the lesson, and the source of an argument you will see repeatedly online.
Now add settings = { theme: "blue" }; as a fourth line and run it again. One of these two writes is refused and the other is not.
The write went through. const fixes which value the name refers to, and the value here is a reference to an object. Changing what is inside the object does not change which object the name points at, so nothing has been violated.
Assigning a whole new object to settings, on the other hand, would change what the name points at, and that is the thing const refuses.
If you want the value itself to stop changing, there is a separate tool for it, and it is not a declaration at all.
Nothing complained and nothing changed. Move both lines inside a function whose first line is "use strict"; and the write becomes a TypeError.
| `const` | `let` | `var` | |
|---|---|---|---|
| Scope | The nearest block | The nearest block | The whole function |
| Reassign later | TypeError | Allowed | Allowed |
| Declare twice in one scope | SyntaxError | SyntaxError | Allowed |
| Must have a value on the line | Yes | No | No |
| Use it in new code | By default | When you reassign | No |
const total = 0; then, ten lines later, total = total + 5;. Where does this go wrong, and when?
It throws a TypeError at the moment the assignment runs, because total was declared const. Everything above that line runs normally first. Contrast it with declaring total twice, which is a SyntaxError and stops the file before anything runs at all.