Programación funcional en JavaScript: fundamentos y práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción a la programación funcional en JavaScript



La programación funcional (PF) es un paradigma de programación en el que los cálculos se consideran como la aplicación de funciones matemáticas. A diferencia del enfoque imperativo, donde escribimos una secuencia de instrucciones que modifican el estado del programa, el estilo funcional se centra en qué se debe calcular, no en cómo hacerlo.



JavaScript, al ser un lenguaje multiparadigma, es excelente para la programación funcional. En el entorno Node.js, este enfoque es especialmente útil al procesar datos, trabajar con flujos y construir aplicaciones de servidor robustas. En este artículo, analizaremos los conceptos clave de la PF con ejemplos prácticos.



Principios fundamentales de la programación funcional



Funciones puras (Pure Functions)

Una función pura es una función que:

  • Siempre devuelve el mismo resultado para los mismos argumentos (determinismo).
  • No tiene efectos secundarios (no modifica variables externas, no imprime en consola, no escribe en archivos).


// Función puraconst add = (a, b) => a + b;

// Función impura (efecto secundario — salida por consola)const impureAdd = (a, b) => { console.log(`Sumando ${a} y ${b}`); return a + b;};

// Función impura (depende del estado externo)let counter = 0;const increment = () => ++counter;


Ventajas de las funciones puras: son fáciles de probar, depurar y paralelizar. Son predecibles y no dependen del contexto de ejecución.



Inmutabilidad (Immutability)

La inmutabilidad significa que los datos, una vez creados, no se modifican. En lugar de modificar un objeto existente, creamos una nueva copia del mismo con los cambios necesarios.



// Enfoque mutable (malo)const user = { name: 'Iván', age: 30 };user.age = 31; // Modificamos directamente

// Enfoque inmutable (bueno)const user2 = { name: 'María', age: 25 };const updatedUser = { ...user2, age: 26 };// El objeto original user2 permanece sin cambios

// Trabajando con arraysconst numbers = [1, 2, 3];const newNumbers = [...numbers, 4]; // [1, 2, 3, 4]// numbers sigue siendo [1, 2, 3]


En Node.js, la inmutabilidad es especialmente importante al trabajar con solicitudes y el estado de la aplicación, para evitar mutaciones inesperadas en el código asíncrono.



Funciones de orden superior y closures



Funciones de orden superior (Higher-Order Functions)

Son funciones que reciben otras funciones como argumentos o las devuelven. Los métodos incorporados de arrays map, filter, reduce son ejemplos clásicos.



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

// map — transforma cada elementoconst doubled = numbers.map(n => n * 2);// [2, 4, 6, 8, 10]

// filter — conserva los elementos que cumplen la condiciónconst evens = numbers.filter(n => n % 2 === 0);// [2, 4]

// reduce — reduce el array a un solo valorconst sum = numbers.reduce((acc, n) => acc + n, 0);// 15


Closures

Un closure es una función que «recuerda» las variables del ámbito en el que fue creada, incluso después de que ese ámbito haya terminado su ejecución.



const createCounter = () => {    let count = 0; // Variable privada    return () => ++count;};

const counter1 = createCounter();console.log(counter1()); // 1console.log(counter1()); // 2

const counter2 = createCounter();console.log(counter2()); // 1 (contador independiente)


Los closures se utilizan ampliamente para crear fábricas de funciones y encapsular el estado en el estilo funcional.



Currying y composición de funciones



Currying

El currying es la transformación de una función que recibe múltiples argumentos en una secuencia de funciones, cada una de las cuales

Blogs

Book Recommendations