Programación Funcional en JavaScript

12 de mayo de 2025

La programación funcional (FP) es un paradigma de desarrollo que trata la computación como la evaluación de funciones matemáticas y evita cambiar el estado o los datos mutables. En JavaScript, este enfoque puede ayudarte a escribir código más limpio, reutilizable y fácil de probar.

¿Qué es la Programación Funcional?

La programación funcional se basa en varios principios clave:

  • Funciones puras: funciones que no tienen efectos secundarios y siempre devuelven el mismo resultado para los mismos argumentos.
  • Inmutabilidad: los datos no cambian. En lugar de modificar una estructura de datos, se crea una nueva.
  • Funciones de primera clase y orden superior: las funciones pueden ser tratadas como valores, pasadas como argumentos y devueltas por otras funciones.
  • Composición: construir funciones complejas a partir de funciones simples.

1. Funciones Puras

Una función pura siempre entrega el mismo resultado con los mismos parámetros y no produce efectos colaterales (como modificar una variable externa o escribir en un archivo).

// Función pura
const sumar = (a, b) => a + b;

console.log(sumar(2, 3)); // 5
console.log(sumar(2, 3)); // 5, siempre el mismo resultado

Una función impura sería:

let total = 0;

function sumarImpuro(a) {
  total += a; // Modifica una variable externa
  return total;
}

2. Inmutabilidad

En programación funcional, los datos son inmutables. Eso significa que en vez de modificar un objeto o arreglo, creas uno nuevo.

const original = [1, 2, 3];
const nuevo = [...original, 4];

console.log(original); // [1, 2, 3]
console.log(nuevo); // [1, 2, 3, 4]

Para objetos:

const persona = { nombre: "Ana", edad: 25 };
const personaNueva = { ...persona, edad: 26 };

console.log(persona); // { nombre: "Ana", edad: 25 }
console.log(personaNueva); // { nombre: "Ana", edad: 26 }

3. Funciones de Orden Superior

Una función de orden superior recibe una función como argumento o devuelve una función.

const saludar = (nombre) => `Hola, ${nombre}`;

const procesar = (callback, nombre) => callback(nombre);

console.log(procesar(saludar, "Luis")); // "Hola, Luis"

Otro ejemplo con arrays:

const numeros = [1, 2, 3, 4, 5];

const pares = numeros.filter((n) => n % 2 === 0); // [2, 4]
const cuadrados = numeros.map((n) => n * n); // [1, 4, 9, 16, 25]
const suma = numeros.reduce((acc, n) => acc + n, 0); // 15

4. Composición de Funciones

La composición permite combinar funciones simples para construir lógica compleja de forma legible.

const agregarUno = (x) => x + 1;
const duplicar = (x) => x * 2;

// Composición manual
const procesar = (x) => duplicar(agregarUno(x));

console.log(procesar(3)); // (3 + 1) * 2 = 8

Con librerías como lodash/fp o Ramda:

// usando lodash/fp
import { flow } from "lodash/fp";

const procesar = flow(agregarUno, duplicar);

console.log(procesar(3)); // 8

5. Aplicación práctica: Filtrar y transformar datos

Caso real: tienes una lista de productos. Quieres aplicar un descuento del 10% solo a los que están disponibles y calcular el total.

const productos = [
  { nombre: "Laptop", precio: 1000, disponible: true },
  { nombre: "Tablet", precio: 500, disponible: false },
  { nombre: "Monitor", precio: 300, disponible: true },
];

const totalConDescuento = productos
  .filter((p) => p.disponible)
  .map((p) => ({ ...p, precio: p.precio * 0.9 }))
  .reduce((acc, p) => acc + p.precio, 0);

console.log(`Total a pagar: $${totalConDescuento}`); // Total a pagar: $1170

6. Ventajas de la Programación Funcional

✅ Código más predecible y fácil de probar
✅ Favorece la reutilización y la composición
✅ Reduce errores derivados de efectos colaterales
✅ Ideal para entornos asincrónicos y programación reactiva

7. Herramientas y Librerías Funcionales

  • Ramda: Utilidades para FP puras.
  • Lodash/fp: Variante funcional de Lodash.
  • RxJS: Programación reactiva y observables.

¿Qué sigue?

La programación funcional te permite crear código más robusto y fácil de mantener. Dominar funciones puras, composición y trabajar con datos inmutables te prepara para desafíos complejos del desarrollo moderno.

Puedes dar el siguiente paso aprendiendo sobre currying, memoization, o monads en JavaScript.