Skip to Content
Course content

36: Higher-Order Functions

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Up until now, we've treated functions as things we call to get a result. But in JavaScript, functions are "first-class citizens." That's a fancy way of saying they're just objects. You can pass them around in variables, shove them into arrays, and—most importantly—pass them as arguments to other functions. When a function does that, or returns another function, we call it a Higher-Order Function (HOF).

I find the best way to wrap your head around this is to build something where the logic needs to be swappable. Let's imagine we're building a checkout system for a store. We have a price, but we need to apply different kinds of discounts depending on the customer.

Defining our raw data and basic strategies

Instead of writing one giant function with a dozen if/else statements for every possible discount type, I'm going to write small, single-purpose functions. These are the "strategies" we'll pass into our HOF later.

const flatDiscount = (price) => price - 10;
const percentageDiscount = (price) => price * 0.9; // 10% off
const vipDiscount = (price) => price * 0.7; // 30% off

Creating the coordinator function

Now, I'll write the Higher-Order Function. Its job isn't to know how to calculate a discount, but to coordinate when it happens. It takes the price and a function (the strategy) as arguments.

const applyDiscount = (price, discountFn) => {
  return discountFn(price);
};

// Using it:
const finalPrice = applyDiscount(100, percentageDiscount); 
console.log(finalPrice); // 90

Correcting a common "reference" blunder

I'll be honest: even after years of doing this, I still occasionally trip over this specific mistake when I'm rushing. I might try to pass a parameter into the discount function inside the HOF call, like this:

// MISTAKE: I'm calling the function immediately instead of passing it
const badPrice = applyDiscount(100, percentageDiscount(100));

If I do this, percentageDiscount(100) executes immediately and returns 90. Then, applyDiscount tries to call 90(100). Since 90 isn't a function, the whole app crashes with a TypeError: discountFn is not a function. I forgot that the HOF expects a recipe (the function reference), not the finished meal (the result of the function). I have to pass percentageDiscount without the parentheses.

Building a function factory

The other side of HOFs is a function that returns another function. This is incredibly powerful for creating specialized tools. What if I want a discount function for any arbitrary percentage? I don't want to hardcode 10% or 30%.

I can create a "factory" function. This is a HOF that configures a new function and hands it back to me.

const createDiscount = (percent) => {
  return (price) => price * (1 - percent / 100);
};

// Now I can generate specific functions on the fly
const tenPercentOff = createDiscount(10);
const fiftyPercentOff = createDiscount(50);

console.log(applyDiscount(100, tenPercentOff)); // 90
console.log(applyDiscount(100, fiftyPercentOff)); // 50

I personally love this pattern because it keeps the core logic (applyDiscount) completely separate from the configuration (createDiscount). It makes the code easier to test and way more flexible.




📋 Practical Task

The Content Formatting Pipeline

You are building a simple blog editor. You need a Higher-Order Function called processText that takes a string of text and a formatting function, returning the transformed string.

Your requirements:

  • Create a function processText(text, formatter) that applies the formatter to the text.
  • Create two simple formatting functions: toUpper (converts text to uppercase) and toSlug (converts text to lowercase and replaces spaces with hyphens).
  • Create a HOF called createRepeatFormatter(count) that returns a function which repeats the input text count times.

Example Output:

processText("Hello World", toUpper); // "HELLO WORLD"
processText("Hello World", toSlug); // "hello-world"
const tripleRepeat = createRepeatFormatter(3);
processText("Hi", tripleRepeat); // "HiHiHi"
Rating
0 0

There are no comments for now.

to be the first to leave a comment.