Underscore.js命令式与函数式编程练习:高阶函数困惑求助
First, let’s clarify these two paradigms with simple, relatable examples—this should help you see the core shift in thinking between them.
What’s Imperative Programming?
Imperative code is all about telling the computer how to do something, step by step. You write explicit loops, conditionals, and mutate variables to reach your result. Think of it like giving a super detailed recipe: "Grab a bowl, add 1 cup flour, stir for 2 minutes, pour in milk, etc."
Example: Filtering even numbers from an array (imperative style):
const numbers = [1, 2, 3, 4, 5]; const evenNumbers = []; for (let i = 0; i < numbers.length; i++) { if (numbers[i] % 2 === 0) { evenNumbers.push(numbers[i]); // Mutate the result array } } console.log(evenNumbers); // [2,4]
Here, you’re controlling every part of the process: initializing the loop, checking each element, and updating the result array manually.
What’s Functional Programming?
Functional code focuses on what you want to achieve, not the step-by-step mechanics. It relies on pure functions (no side effects, same input always gives the same output) and higher-order functions (functions that take other functions as arguments or return them) to compose logic. Instead of mutating data, you transform it.
Using Underscore.js, the same even number filter becomes:
const numbers = [1, 2, 3, 4, 5]; const evenNumbers = _.filter(numbers, function(num) { return num % 2 === 0; }); console.log(evenNumbers); // [2,4]
Here, you’re telling Underscore: "Filter this array to keep elements where the provided function returns true." You don’t worry about writing the loop—you focus on the rule for which elements to keep.
Practical Steps to Build Functional Solutions with Underscore
If you’re stuck on how to start, try these actionable steps:
Step 1: Define input/output first
Forget loops or variables for a minute. Ask: "Given X input, what should the final output look like?" For example, if you need the sum of squared even numbers, input is an array of numbers, output is a single number.Step 2: Break the problem into tiny pure functions
For the sum example:- A function to check if a number is even (
isEven(num) => num % 2 === 0) - A function to square a number (
square(num) => num * num) - Then use Underscore’s built-ins to chain these together.
- A function to check if a number is even (
Step 3: Replace loops with Underscore’s higher-order functions
- Use
_.mapwhen you need to transform every element in an array. - Use
_.filterwhen you need to select elements matching a condition. - Use
_.reducewhen you need to aggregate values into a single result (sums, averages, etc.). - Avoid mutating original data—Underscore’s functions return new values by default, so you don’t have to worry about accidentally changing the input.
- Use
Step 4: Practice refactoring imperative code
Take a small imperative task you’ve already written (like a loop that capitalizes strings) and rewrite it using Underscore functions. Start simple—don’t jump into complex compositions right away.
Key Mindset Shift
The biggest change is stopping thinking about "how to iterate" and starting to think about "how to transform data". Instead of managing state (like updating a counter or pushing to an array), let Underscore handle the iteration logic while you focus on the business rules (the predicates and transform functions).
For example, instead of writing a loop to capitalize every string in an array, use _.map with a function that capitalizes a single string.
Remember, it’s okay to take it slow. Master one Underscore function at a time, get comfortable with it, then move to combining them.
内容的提问来源于stack exchange,提问作者josh_c

