You: “Hey, I keep hearing about functional programming. It sounds cool, but what is it really, and how is it different from what I already do in JavaScript?”
Me: Great question! Let’s break it down step-by-step and compare functional programming (FP) with the traditional imperative way of coding.
In imperative programming, you write step-by-step instructions on how to do something. It’s all about the sequence of tasks—updating variables, using loops, and modifying state directly.
In functional programming, you focus on what you want to do. You use pure functions, avoid direct mutations, and leverage declarative tools like map, filter, and reduce.
Let’s see this with side-by-side examples using a CRUD (Create, Read, Update, Delete) scenario for managing a list of users.
Here’s an imperative example where we mutate the original array:
let users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; function addUser(users, newUser) { users.push(newUser); // Directly modifies the array } addUser(users, { id: 3, name: 'Charlie' }); console.log(users);
Issues:
Here’s the functional approach, where we return a new array instead of mutating it:
const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; const addUser = (users, newUser) => [...users, newUser]; // Returns a new array const newUsers = addUser(users, { id: 3, name: 'Charlie' }); console.log('Original:', users); console.log('New:', newUsers);
Benefits:
Here’s an example where we directly change an object inside the array:
let users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; function updateUser(users, id, newName) { for (let i = 0; i < users.length; i++) { if (users[i].id === id) { users[i].name = newName; // Directly mutates the object break; } } } updateUser(users, 1, 'Alicia'); console.log(users);
Issues:
Here’s how we do it functionally using map and immutability:
const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; const updateUser = (users, id, newName) => users.map(user => user.id === id ? { ...user, name: newName } : user ); const updatedUsers = updateUser(users, 1, 'Alicia'); console.log('Original:', users); console.log('Updated:', updatedUsers);
Benefits:
Here’s the imperative version using a loop and direct modifications:
let users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; function addUser(users, newUser) { users.push(newUser); // Directly modifies the array } addUser(users, { id: 3, name: 'Charlie' }); console.log(users);
Issues:
Using filter, we can declaratively express the intention:
const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; const addUser = (users, newUser) => [...users, newUser]; // Returns a new array const newUsers = addUser(users, { id: 3, name: 'Charlie' }); console.log('Original:', users); console.log('New:', newUsers);
Benefits:
|
Imperative |
Functional | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Data Mutation |
Mutates the original data (e.g., push, splice) | Avoids mutation; creates new data structures | ||||||||||||||||||
Step-by-step, more verbose | Declarative and concise | |||||||||||||||||||
Side Effects | More prone to unexpected side effects | Pure functions eliminate side effects | ||||||||||||||||||
|
What to achieve (use higher-order functions) | |||||||||||||||||||
Tools Used | Loops, conditionals | map, filter, reduce, spread operator |
? Why Choose Functional Programming?
Your code becomes easier toreason about and test. Avoiding side effects makes bugs less likely. It’s more concise
anddeclarative, reducing mental load.
The above is the detailed content of What is Functional Programming, and How Can You Do It in JavaScript?. For more information, please follow other related articles on the PHP Chinese website!