Course outline · 0% complete

0/29 lessons0%

Course overview →

Projects: cart calculator and text stats

lesson 9-2 · ~14 min · 29/29

Project A: the cart calculator

Every checkout page runs this exact math. The model is an array of objects again, each with a price and a qty. The rules:

  1. Each line costs price × qty.
  2. The total is the sum of all lines, a perfect job for reduce (lesson 7-3).
  3. Orders over $50 earn a 10% discount, so the customer pays total × 0.9.
  4. Money is displayed with toFixed(2) (lesson 8-2), always at the last step.

Notice how small each piece is. sum + item.price * item.qty is the whole business logic of a checkout line. Projects feel hard until you write the data shape down, then every function becomes a one-liner you already know.

The full cart calculator

Every checkout page runs this math. One reduce produces the total, and an if applies the discount rule on top of it.

const cart = [
  { name: "mouse", price: 25, qty: 2 },
  { name: "cable", price: 4.5, qty: 3 }
];

function cartTotal(items) {
  return items.reduce((sum, item) => sum + item.price * item.qty, 0);
}

const total = cartTotal(cart);
console.log(total.toFixed(2));

if (total > 50) {
  console.log((total * 0.9).toFixed(2));
} else {
  console.log("no discount");
}

Output

63.50
57.15

Tracing the reduce by hand confirms the total. The mouse line is 25 × 2 = 50, the cable line is 4.5 × 3 = 13.5, and the accumulator starting at 0 folds them into 63.5.

The multiplication happens inside the arrow, as sum + item.price * item.qty, which is the detail that makes this a real checkout rather than a plain sum. Precedence works in your favor here, since * binds tighter than +, so each line's cost is computed before it joins the running total.

The discount applies because 63.5 clears the 50 threshold, and 63.5 * 0.9 gives 57.15. Both printed values go through toFixed(2) at the last possible moment, keeping every calculation on real numbers and leaving formatting to the display step as lesson 8-2 advised.

Project B: text statistics

Now a tool that reads a sentence and reports on it, the seed of every word counter and search engine tokenizer. The plan uses only tools you own:

  1. split(" ") from lesson 8-1 turns the sentence into an array of words.
  2. Word count is just .length (lesson 4-1).
  3. Counting long words is filter + .length (lesson 7-1).
  4. Finding the longest word is the biggest-so-far loop from lesson 4-3, comparing w.length instead of the values themselves.

That is the entire project. You are about to write it yourself.

The full text statistics tool

Three questions about one sentence, answered with the string toolkit and the array toolkit together.

const text = "the quick brown fox jumps over the lazy dog";

const words = text.split(" ");
console.log(words.length);

console.log(words.filter(w => w.length > 4).length);

let longest = words[0];
for (const w of words) {
  if (w.length > longest.length) {
    longest = w;
  }
}
console.log(longest);

Output

9
3
quick

The first stage does the work everything else depends on. text.split(" ") turns one string into an array of nine words, after which the word count is simply .length.

The long-word count chains a filter with a .length, which is the standard way to count matches without a loop. Three words clear four letters: quick, brown, and jumps.

The longest-word search is the biggest-so-far loop from lesson 4-3, comparing w.length against longest.length while returning a whole word. quick wins over brown and jumps despite all three having five letters, because the strict > keeps the earliest one and only replaces the champion on a genuine improvement.

Tracing a smaller cart

For a cart of { price: 10, qty: 2 } and { price: 5, qty: 1 }, cartTotal returns 25.

Each line contributes price × qty, so the first line is 10 × 2 = 20 and the second is 5 × 1 = 5. The reduce starts at 0 and folds them in one at a time: 0 + 20 = 20, then 20 + 5 = 25.

No discount applies to this order, since the rule requires a total above 50 and 25 falls well short, so the customer pays the full 25. Tracing a reduce this way, one accumulator value at a time, is the fastest way to check that a total is correct before trusting it with real money.

Three Python habits, translated

Course finished. The three Python tools this course replaced most often map cleanly onto JavaScript equivalents, and being able to state the trio from memory is a good sign the translation has taken hold.

PythonJavaScriptLesson
f-strings, f"{name}"template literals, ` ${name} `1-3
sum(xs) with a start valuereduce with a start value7-3
dict.items()Object.entries(obj)5-2

Every one of those replacements is a spelling change on top of an idea you already had. That is the honest summary of this whole course: your Python knowledge did the heavy lifting, and JavaScript mostly asked you to learn new names for it, plus a handful of genuinely new rules such as references, truthiness, and the two "nothing" values.

The next courses build directly on this foundation, and none of them start over. map, filter, reduce, objects, and functions as values are the vocabulary that React components, Node servers, and TypeScript types are all written in.