Introducción a la Programación Funcional
Qué es la programación funcional, sus principios clave y por qué importa en JavaScript
¿Qué es la Programación Funcional?
La Programación Funcional (PF) es un paradigma que trata la computación como la evaluación de funciones matemáticas. En lugar de cambiar el estado y mutar datos, la PF enfatiza la inmutabilidad, las funciones puras y el código declarativo.
JavaScript es un lenguaje multiparadigma que admite programación funcional junto con estilos orientados a objetos e imperativos. El JavaScript moderno y librerías como React han adoptado conceptos de PF, lo que la hace esencial para desarrolladores frontend.
🎯 Principios fundamentales de la PF
- Funciones puras: La misma entrada siempre produce la misma salida, sin efectos secundarios.
- Inmutabilidad: Los datos no se modifican; se crean nuevos datos en su lugar.
- Funciones de primera clase: Las funciones son valores que pueden pasarse y almacenarse.
- Funciones de orden superior: Funciones que reciben o retornan otras funciones.
- Código declarativo: Describe qué hacer, no cómo hacerlo.
- Composición: Construye funciones complejas a partir de funciones simples.
Imperativo vs Declarativo
El cambio de mentalidad clave en la PF es pasar de la programación imperativa (cómo hacerlo) a la declarativa (qué hacer).
// Imperative: HOW to do it (step by step)
const numbers = [1, 2, 3, 4, 5];
const doubled = [];
for (let i = 0; i < numbers.length; i++) {
doubled.push(numbers[i] * 2);
}
console.log(doubled); // [2, 4, 6, 8, 10]
// Declarative/Functional: WHAT to do
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// The declarative version:
// - Is shorter and more readable
// - Expresses intent clearly
// - Doesn't mutate external state
// - Returns a new array
Funciones como ciudadanos de primera clase
En JavaScript, las funciones son ciudadanos de primera clase, lo que significa que pueden:
// 1. Assigned to variables
const greet = function(name) {
return `Hello, ${name}!`;
};
// 2. Passed as arguments
function executeCallback(callback, value) {
return callback(value);
}
executeCallback(greet, 'World'); // "Hello, World!"
// 3. Returned from functions
function createMultiplier(multiplier) {
return function(number) {
return number * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
double(5); // 10
triple(5); // 15
// 4. Stored in data structures
const operations = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
};
operations.add(2, 3); // 5
¿Por qué Programación Funcional?
🧪 Pruebas más fáciles
Las funciones puras son fáciles de probar: misma entrada, misma salida. Sin mocks ni configuración compleja.
🐛 Menos bugs
La inmutabilidad elimina una clase entera de bugs por mutaciones inesperadas.
🔄 Reutilizable
Funciones pequeñas y enfocadas se pueden componer para construir comportamientos complejos.
🧠 Predecible
Las funciones puras sin efectos secundarios son predecibles y fáciles de razonar.
PF en JavaScript moderno
// Array methods embrace FP
const users = [
{ name: 'Alice', age: 25, active: true },
{ name: 'Bob', age: 30, active: false },
{ name: 'Carol', age: 35, active: true },
];
// Chain declarative operations
const result = users
.filter(user => user.active) // Keep active users
.map(user => user.name) // Extract names
.map(name => name.toUpperCase()); // Transform to uppercase
console.log(result); // ['ALICE', 'CAROL']
// Each method:
// - Returns a new array (immutability)
// - Takes a function as argument (higher-order)
// - Describes what, not how (declarative)
PF en React
// React components are essentially functions
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Same input (props) → Same output (JSX)
// This is a pure function!
// useState embraces immutability
function Counter() {
const [count, setCount] = useState(0);
// Don't mutate state directly
// setCount(count++) ❌
// Create new state instead
// setCount(count + 1) ✅
// setCount(prev => prev + 1) ✅
return (
<button onClick={() => setCount(prev => prev + 1)}>
Count: {count}
</button>
);
}
// useReducer is pure function: (state, action) => newState
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
PF vs POO
| Aspecto | Programación Funcional | Programación Orientada a Objetos |
|---|---|---|
| Unidad principal | Funciones | Objetos/Clases |
| Estado | Inmutable, pasado explícitamente | Mutable, encapsulado en objetos |
| Efectos secundarios | Evitados o controlados | Comunes (el método modifica el estado) |
| Flujo de datos | Transformaciones mediante funciones | Mensajes entre objetos |
| Reutilización | Composición | Herencia |
💡 Cómo empezar con la PF
- • Empieza usando
map,filteryreduceen lugar de bucles - • Evita mutar variables: usa
consty crea nuevos objetos/arrays - • Extrae funciones pequeñas y enfocadas que hagan una sola cosa
- • Piensa en transformaciones de datos como pipelines
- • Practica: reescribe código imperativo en estilo declarativo