A program with two variables
Here is a six-line program that keeps a game score. The JavaScript engine runs it top to bottom, one line at a time. Memory starts empty: no variable exists until a line makes one.
Making variables
A variable is a named box in memory that holds a value. let makes a new box called score, and = puts 0 in it. A box made with let can get a new value later.
const also makes a named box, here maxLives holding 3, but this box is locked: it can never get a new value. So a const must get its value on the line that makes it.
Changing and reading
On line 3 the right side of = runs first. The engine reads the value in score, which is 0, and works out 0 + 10. The answer is 10. Nothing is stored yet.
Now = stores 10 in score, and the old 0 is gone. In JavaScript, = does not mean "is equal to". It means: put the value on the right into the box on the left.
Line 4 works the same way. The engine reads 10, adds 5 and stores 15 in score. A let variable can change as often as you like; it always holds its latest value.
console.log reads both boxes and writes their values to the console, with a space between them: 15 3. Reading a variable does not change it; score still holds 15.
A const stays put
Line 6 tries to put 4 in maxLives. The box is locked, so the engine refuses: it throws a TypeError, an error message, and the program stops. maxLives still holds 3.
Good habits
A name may use letters, digits, _ and $, but cannot start with a digit or be a reserved word such as const or if. Case matters: score and Score are different boxes. JavaScript names are usually written like maxLives.
A good habit: make every variable with const. Switch to let only when the value really has to change, like score. Older code uses var; modern code uses let and const instead.
What happens
// step 1/10 · program file score.js, 6 lines engine runs line 1, then line 2, ... memory score = (none yet) maxLives = (none yet)
The box is a simplification. The ECMAScript specification calls a variable a binding: a name that refers to a value, kept in an environment record for that block of code. Strictly, the binding exists from the start of its block but cannot be used until its line runs (the temporal dead zone). Chrome and Node.js (the V8 engine) print "TypeError: Assignment to constant variable."; Firefox says "invalid assignment to const 'maxLives'". The error happens when line 6 runs, so lines 1 to 5 have already run and 15 3 is printed first.