L58 - Programación Funcional
🧠 Concepto
Section titled “🧠 Concepto”La programación funcional es un paradigma de programación que trata la computación como la evaluación de funciones matemáticas y evita el cambio de estado y los datos mutables. No es un concepto nuevo, pero ha ganado gran popularidad en JavaScript moderno.
Principios fundamentales
Section titled “Principios fundamentales”1. Funciones puras (Pure functions)
Section titled “1. Funciones puras (Pure functions)”Una función pura cumple dos condiciones:
- Misma entrada → misma salida (determinismo).
- Sin efectos secundarios (no modifica variables externas, no escribe en consola/archivos/DB).
// ❌ Impura: modifica una variable externalet total = 0;function agregarImpuro(valor) { total += valor; return total;}
// ✅ Pura: no modifica nada externofunction agregarPuro(total, valor) { return total + valor;}
// ❌ Impura: tiene efecto secundario (console.log)function doble(x) { console.log(`Calculando doble de ${x}`); return x * 2;}
// ✅ Purafunction doblePuro(x) { return x * 2;}2. Inmutabilidad
Section titled “2. Inmutabilidad”Los datos no se modifican: se crean nuevos datos a partir de los originales.
// ❌ Mutaciónconst usuario = { nombre: 'Ana', edad: 25 };usuario.edad = 26; // ❌ Mutamos el objeto original
// ✅ Inmutabilidadconst usuarioActualizado = { ...usuario, edad: 26 };// usuario original no cambia
// ❌ Mutación en arraysconst frutas = ['manzana', 'pera'];frutas.push('uva'); // ❌
// ✅ Inmutabilidadconst nuevasFrutas = [...frutas, 'uva'];// oconst nuevasFrutas2 = frutas.concat('uva');3. Funciones de orden superior (Higher-Order Functions)
Section titled “3. Funciones de orden superior (Higher-Order Functions)”Son funciones que reciben funciones como argumento o devuelven una función.
// Recibe una funciónfunction operar(a, b, fn) { return fn(a, b);}
operar(5, 3, (x, y) => x + y); // 8operar(5, 3, (x, y) => x * y); // 15
// Devuelve una funciónfunction crearMultiplicador(factor) { return function(numero) { return numero * factor; };}
const duplicar = crearMultiplicador(2);const triplicar = crearMultiplicador(3);
console.log(duplicar(5)); // 10console.log(triplicar(5)); // 15💻 Métodos funcionales de array
Section titled “💻 Métodos funcionales de array”const numeros = [1, 2, 3, 4, 5];
// map: transforma cada elementoconst cuadrados = numeros.map(n => n ** 2); // [1, 4, 9, 16, 25]
// filter: selecciona elementosconst pares = numeros.filter(n => n % 2 === 0); // [2, 4]
// reduce: acumulaconst suma = numeros.reduce((acc, n) => acc + n, 0); // 15
// find: primer elemento que cumpleconst mayorQue3 = numeros.find(n => n > 3); // 4
// some / everyconst algunPar = numeros.some(n => n % 2 === 0); // trueconst todosPares = numeros.every(n => n % 2 === 0); // false📝 Composición de funciones
Section titled “📝 Composición de funciones”En lugar de heredar (POO), en programación funcional se componen funciones pequeñas:
const aMayusculas = str => str.toUpperCase();const quitarEspacios = str => str.trim();const agregarExclamacion = str => `${str}!`;
// Composición manualconst resultado = agregarExclamacion(aMayusculas(quitarEspacios(' hola ')));console.log(resultado); // 'HOLA!'
// Composición con helperfunction componer(...fns) { return function(valorInicial) { return fns.reduceRight((valor, fn) => fn(valor), valorInicial); };}
const transformar = componer(agregarExclamacion, aMayusculas, quitarEspacios);console.log(transformar(' hola ')); // 'HOLA!'🎯 Composición vs Herencia
Section titled “🎯 Composición vs Herencia”| Programación Funcional | POO (Herencia) |
|---|---|
| Compone funciones pequeñas | Hereda de clases padre |
| Datos inmutables | Estado mutable |
| Sin efectos secundarios | Los métodos pueden mutar |
| Más predecible y testeable | Puede crear jerarquías rígidas |
Evita el this problemático | this es central |
⚠️ Errores comunes
Section titled “⚠️ Errores comunes”- Mutar argumentos: modificar arrays/objetos que recibes como parámetro.
- Mezclar paradigmas sin cuidado: no pasa nada, pero sé consciente de cuándo mutas.
- Olvidar el
returnimplícito: en arrow functions de una línea es opcional, pero en cuerpos con llaves es obligatorio. - No usar
...para copiar objetos/arrays profundos:...hace copia superficial (shallow copy).
// Copia superficial vs profundaconst original = { a: 1, b: { c: 2 } };const copiaSuperficial = { ...original };copiaSuperficial.b.c = 99; // ❌ Modifica original también
// Deep clone (una opción)const copiaProfunda = JSON.parse(JSON.stringify(original));🎯 Regla de oro: prefiere funciones puras e inmutabilidad. Tu código será más predecible, testeable y fácil de depurar.