JS Sketchbooksee JavaScript think ✏️
← back to phase 3

3.11 — Checkpoint: the tip calculator brain

The Phase 3 finale — and it works like real software does. The commission: a tip calculator brain. Dinner cost 1200, the service deserves 10%, four friends are splitting. What does each person pay?

You could write one big function that does everything. Professionals don’t. They build small pure functions and compose them — each one returning its answer so the next can build on it. This is why lesson 3.3 was so insistent about return over console.log: a returned value can feed another function; printed text can’t feed anything. Today that investment pays out in full.

watch it happen
function tipAmount(bill, percent) {
  return bill * percent / 100;
}

function totalWithTip(bill, percent) {
  return bill + tipAmount(bill, percent);
}

function perPerson(bill, percent, people) {
  return totalWithTip(bill, percent) / people;
}

console.log(perPerson(1200, 10, 4));

Three definitions, each tiny, each PURE (3.10): inputs through parameters, answers through return, no printing inside. Notice the dependencies: totalWithTip calls tipAmount; perPerson calls totalWithTip. A brain made of three cells.

bill 1200 · tip 10% · 4 peopletipAmounttotalWithTipperPersoneach returned value feeds the next function — no console.log inside
console(nothing logged yet)
under the hood

The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”

What you just used is called function composition: building bigger behavior by feeding one function’s return value into another. It only works because every piece returns (3.3) and every piece is pure (3.10) — no hidden state, so the only thing connecting them is visible values. When you read professional code, this is most of what you’ll see: small verbs, composed.

💼 On the job — your career quietly begins here: pure, composed functions are exactly what unit tests are written against. expect(tipAmount(1200, 10)).toBe(120) — one line, no setup, no browser, no server. In Phase 10 you write exactly that with Vitest. The functions you wrote today would pass unchanged. You didn’t just finish functions; you built your first testable unit.

Phase 3, complete: machines → parameters → return → functions-as-values → scope → the call stack → closures → callbacks → recursion → purity → composition. Every later phase spends this vocabulary. Next stop, Phase 4: what happens when data comes in groups.

your turn

⌨️ part 1 — the smallest brain cell

Start the commission with the smallest piece: a pure function that computes a tip. Nothing printed inside — it RETURNS.

requirements:

  • A function named tipAmount with two parameters: bill, then percent.
  • It RETURNS bill × percent ÷ 100 — pure: no printing, no outside variables.
  • Prove it: print tipAmount(1200, 10).

when you press RUN, the console must show exactly:

120

⌨️ part 2 — machines feeding machines

Now the composition: two more pure functions, each one CALLING the previous one and building on its returned value. tipAmount is already in the editor.

requirements:

  • A function named totalWithTip (parameters: bill, percent) that returns the bill PLUS the tip — and it must get the tip by calling tipAmount, not by re-doing the math.
  • A function named perPerson (parameters: bill, percent, people) that returns the total split evenly — by calling totalWithTip.
  • The grand finale: print perPerson(1200, 10, 4).

when you press RUN, the console must show exactly:

330

✏️ Quick check 1

Type what tipAmount(600, 10) returns:

✏️ Quick check 2

Composition only works because these functions ___ their answers instead of printing them. Type the keyword.

✏️ Quick check 3

Compose in your head: type what perPerson(1000, 20, 2) returns:

teach it back

🗣️ Now teach it back

The Phase 3 graduation speech: explain to a friend how the tip calculator works as three composed pure functions — and why building it that way beats one big function.

Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.

a few sentences, minimum — you’ve got this
to remember
Composition: small pure functions feeding each other through RETURN values. The chute (3.3) was the whole point.
The relay: 120 → 1320 → 330 — each return replaces its call and becomes the next function’s ingredient.
Change stays contained: new percent = new argument; new rule = touch one function. The others never notice.
🎓 Phase 3 complete — and expect(tipAmount(1200,10)).toBe(120) is a Vitest unit test you can already write.
next: 4.1 Arrays →