Exercise 9 of 10 · Putting it together
Rainfall Week
What you will make
A seven-day rainfall chart with a bar for every day, the week added up underneath it, and the wettest of the seven days picked out by its number.
The one new idea: a value declared with let above a loop carries a running total from pass to pass
Adding up as you go, and holding on to the best you have seen, sit underneath a huge number of ordinary programs: a basket total, a high score, a longest streak, a loading bar. Each one is a value declared with let above a loop and changed inside it, which is also the clearest reason JavaScript has let as well as const.
Go straight to the code ↓Two values that have to survive the loop
There is almost no new syntax in this exercise. An array, a for...of loop, an if, a template literal, + —
every piece of it has already been on screen. That is the point: holding five ideas separately is not the same
as getting them to cooperate in one program, and that gap is where most people stall.
The one new sign is >, which is the >= from the umbrella check with its equals sign taken off: strictly
bigger, so a tie does not count.
The idea that joins them up is small. A name made above a loop is still standing on every pass, so whatever one pass leaves in it, the next pass finds. Anything the loop must carry from day to day belongs above it, and two things here are worth carrying that way.
A running total. Start a name at zero above the loop, then inside it write total = total + mm.
JavaScript works out the right-hand side first — whatever the total held a moment ago, plus this pass's
measurement — and stores it back under the same name.
The best so far. Start a second name at zero, then inside the loop ask whether this pass beats it:
if (mm > wettestMm). When it does, store the new number. By the final pass, the largest so far is simply
the largest.
Keeping which day it was is one more line inside the same if: the amount and the day are one fact in two
halves.
Why these are let and rain is const
You have met both words. const promises the name will never be pointed at a different value; let is for a
name meant to move, like the countdown's counter or the scoreboard's player, score and bar. A running total is
the clearest case of all — it exists in order to change — so it is declared with let, and so are the record
holder and the day counter. Point a const at something new and
JavaScript stops with TypeError: Assignment to constant variable.
rain stays const, because the measurements never change, and so does bar: each pass builds a brand new
one rather than changing the old.
The word is half the story. Where the declaration sits is the other half:
for (const n of [1, 2, 3]) {
let total = 0;
total = total + n;
console.log(`this pass: ${total}`);
}this pass: 1
this pass: 2
this pass: 3Nothing adds up, because the line setting it to zero runs again every time round. Worse, a let made inside
braces belongs to those braces: after the loop that name does not exist at all, and asking for it gives
ReferenceError: total is not defined.
A worked example
Four marks from a notebook, with the total printed on every pass so you can watch it climb:
const marks = [4, 7, 2, 7];
let total = 0;
let best = 0;
for (const mark of marks) {
total = total + mark;
if (mark > best) {
best = mark;
}
console.log(`mark ${mark} total ${total}`);
}
console.log(`best mark: ${best}`);mark 4 total 4
mark 7 total 11
mark 2 total 13
mark 7 total 20
best mark: 7total never drops back to zero, because the line that starts it sits above the loop and runs once. best
ends on 7 and does not move on the last pass, even though that mark is a 7 as well: 7 > 7 is false, so a
tie leaves the first one holding the record.
Your turn
The editor holds a week of rainfall. rain is an array of seven measurements in millimetres, and the loop
prints a row for each: the day number, a bar of one # per millimetre, then the measurement. Day two was
dry, so its bar is empty — correct, not broken.
Press Run first. The chart is right; the two lines beneath it are not. The total reads 0 mm, and the wettest day comes out as day 0, which is not one of the seven.
Both additions go inside the loop's braces.
- Add this day's rain to
total. - If this day beats
wettestMm, store both the new amount and the day number.
All three names already exist above the loop, holding zero: you are changing them, not making them. And
day = day + 1 is a running total too, so the shape of your first line is on screen already.
If something goes wrong
If the program stops with ReferenceError: mm is not defined, the new lines are below the loop's closing
brace rather than inside it. mm is the loop's own name and is gone once the loop finishes, so move the lines
up inside the braces.
If the total still reads 0 mm with no error, look for let in front of total inside the loop. That makes a
second total belonging to the braces; the addition goes into it, and the one the last lines print never
moves. Written as let total = total + mm, the same slip stops the program with
ReferenceError: Cannot access 'total' before initialization. Either way, delete the let: the name exists
already. A line reading only total + mm also leaves 0, because the sum is worked out and never stored.
If the amount is right but the day is wrong, look at the if. Either the line storing the day is missing, or
the if has no braces, in which case only the first line belongs to it and the second runs every pass,
leaving day 7 on the board. Tidy indentation counts for nothing; the braces decide.
A TypeError about a constant variable means a const is being changed: either a value that moves was made
with const, or a single = has crept into the if and is trying to store into mm, which the loop made
with const.
Once the week adds up, change a number in rain and run it again: the bar, the total and the wettest day
should all move on their own.
Write your code
Runs in your browser. Press Run (or Ctrl/Cmd+Enter) and the output is checked for you.
Press Esc then Tab to move keyboard focus out of the code editor.
Output will appear here after you run your code.The runtime is starting in the background. You can type now — it will be ready before you are.
The answer appears here once you have run your code at least once.
Things that often go wrong here
- Declaring the running total with const
- const means the name will never be pointed at anything else, so the first time the loop tries to change it JavaScript stops with TypeError: Assignment to constant variable. A total that is being collected exists in order to change, which is exactly what let is for. The array of measurements never changes, so it stays const.
- Declaring total again inside the loop's braces
- The total already exists above the loop, and let inside the braces makes a second one that belongs to those braces alone. Written as let total = total + mm, JavaScript stops with ReferenceError: Cannot access 'total' before initialization, because inside the braces the name now means the new total, and it is being read before it holds anything. Written as let total = 0 followed by the addition, nothing crashes, but that inner total is built fresh on every pass and gone at the closing brace, while the one the last lines print never moves from 0. The name exists already: change it, do not declare it.
- Leaving the braces off the if
- Without braces an if governs the single line after it and nothing more. The amount is then remembered only on a record-breaking day, while the day number is stored on every pass, so the last line claims day 7 with 14 mm even though day 4 was the wet one. The indentation looks convincing and counts for nothing: in JavaScript the braces decide.
- Remembering the amount but not the day
- An if that updates only the amount leaves the day holding the zero it started with, so the final line reports day 0, which is not one of the seven. Both lines belong inside the same if, because they are two halves of one fact.
- Writing the comparison with one equals sign
- One equals sign puts a value into a name and three ask whether values match, and an if needs a question. Here it fails loudly, because the name the for line hands you is a const: JavaScript stops with TypeError: Assignment to constant variable. The test you want is greater-than anyway, not equals.
Want a blank editor instead? Open the JavaScript playground.