Skip to content

JavaScript Tutorial Functional JavaScript

Functional Style in Practice

Lesson 206 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

Let’s apply the ideas of the chapter to one realistic task: summarise a list of orders.

script.js
JS
const orders = [
  { id: 1, customer: "Maya", items: [{ name: "Book", price: 12, qty: 2 }], status: "paid" },
  { id: 2, customer: "Arjun", items: [{ name: "Pen", price: 2, qty: 10 }, { name: "Notebook", price: 4, qty: 1 }], status: "pending" },
  { id: 3, customer: "Maya", items: [{ name: "Bag", price: 35, qty: 1 }], status: "paid" }
];

// small, pure building blocks
const lineTotal = item => item.price * item.qty;
const orderTotal = order => order.items.map(lineTotal).reduce((a, b) => a + b, 0);
const isPaid = order => order.status === "paid";
const sum = numbers => numbers.reduce((a, b) => a + b, 0);

// compose them
const paidRevenue = orders => sum(orders.filter(isPaid).map(orderTotal));

console.log(paidRevenue(orders)); // → 59

Each helper does one thing and can be tested alone: lineTotal({ price: 12, qty: 2 }) is 24.

Grouping with reduce

script.js
JS
const orders = [
  { customer: "Maya", total: 24 },
  { customer: "Arjun", total: 24 },
  { customer: "Maya", total: 35 }
];

const totalsByCustomer = orders.reduce(
  (totals, order) => ({ ...totals, [order.customer]: (totals[order.customer] ?? 0) + order.total }),
  {}
);

console.log(totalsByCustomer); // → { Maya: 59, Arjun: 24 }

No variable was changed, and each step produced a new object.

Immutable update of one order

script.js
JS
const orders = [
  { id: 1, status: "pending" },
  { id: 2, status: "pending" }
];

const markPaid = (list, id) =>
  list.map(order => (order.id === id ? { ...order, status: "paid" } : order));

const updated = markPaid(orders, 2);

console.log(orders[1].status);   // → pending   (original untouched)
console.log(updated[1].status);  // → paid

Sorting without surprises

script.js
JS
const byTotalDesc = (a, b) => b.total - a.total;

const orders = [{ total: 24 }, { total: 59 }, { total: 35 }];
const ranked = [...orders].sort(byTotalDesc);   // copy first: sort mutates

console.log(ranked.map(o => o.total)); // → [59, 35, 24]
console.log(orders.map(o => o.total)); // → [24, 59, 35]

Putting the page on top

The calculations are pure. The page updating is the side effect, kept in one small place.

index.html
HTML
<ul id="report"></ul>
<script>
  const sales = [{ product: "Book", amount: 24 }, { product: "Pen", amount: 20 }, { product: "Book", amount: 12 }];

  // pure: build the data
  const totals = sales.reduce((acc, s) => ({ ...acc, [s.product]: (acc[s.product] ?? 0) + s.amount }), {});
  const lines = Object.entries(totals).map(([product, total]) => `${product}: $${total}`);

  // impure: render
  document.querySelector("#report").replaceChildren(
    ...lines.map(text => Object.assign(document.createElement("li"), { textContent: text }))
  );
</script>

What you gained

  • Each function is small, named and testable.
  • Data flows in one direction through the pipeline.
  • Nothing is changed behind your back.

When to use a loop instead

If a for...of loop makes a task clearer (especially with break, await or several outputs at once), use it. Functional style is a way of thinking about data flow, not a rule against loops.

Exercise: average rating

Given an array of reviews { product, rating }, write a pure function that returns the average rating for a given product, or 0 if there are no reviews.

Show a possible solution
script.js
JS
const averageRating = (reviews, product) => {
  const ratings = reviews.filter(r => r.product === product).map(r => r.rating);
  return ratings.length === 0 ? 0 : ratings.reduce((a, b) => a + b, 0) / ratings.length;
};

const reviews = [{ product: "Pen", rating: 4 }, { product: "Pen", rating: 5 }, { product: "Book", rating: 3 }];
console.log(averageRating(reviews, "Pen"));   // → 4.5
console.log(averageRating(reviews, "Lamp"));  // → 0