JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
36: Higher-Order Functions
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) andtoSlug(converts text to lowercase and replaces spaces with hyphens). - Create a HOF called
createRepeatFormatter(count)that returns a function which repeats the input textcounttimes.
Example Output:
processText("Hello World", toUpper); // "HELLO WORLD"
processText("Hello World", toSlug); // "hello-world"
const tripleRepeat = createRepeatFormatter(3);
processText("Hi", tripleRepeat); // "HiHiHi"There are no comments for now.