Recursividad en JavaScript

La recursividad en programación es útil para resolver tareas descomponiéndolas en subtareas.

recursividad-javascript

La recursividad es una técnica que puede resultar útil para resolver tareas que se descomponen en subtareas similares. Es una herramienta presente en la mayoría de lenguajes de programación, y en JavaScript aunque quizá no sea la técnica más usada, no es una excepción. Se utiliza en contextos donde el problema se puede expresar como una repetición del mismo patrón con una entrada reducida.

Los algoritmos de recursividad se suele enseñar mostrando fórmulas matemáticas, como la fórmula de Fibonacci. Pero para facilitar su compresión vamos a verlo con una analogía más práctica: imaginemos una persona subiendo una escalera een donde hay un objeto en cada peldaño, la persona deberá subir peldaño a peldaño y recoger cada objeto.

Recursividad

Técnincamente, la recursividad en JavaScript se expresa con una función que se llama a sí misma hasta que se alcanza una condición que detiene el proceso. En nuestro caso, imaginamos una escalera con n peldaños. En cada uno hay un objeto. Queremos recogerlos todos, uno por uno, desde el primer peldaño hasta el último.

function recogerObjetos(peldano) {
if (peldano === 0) return;
recogerObjetos(peldano - 1);
console.log(`Recogemos objeto del peldaño ${peldano}`);
}
recogerObjetos(5);

Este código imprime:

Recogemos objeto del peldaño 1
Recogemos objeto del peldaño 2
Recogemos objeto del peldaño 3
Recogemos objeto del peldaño 4
Recogemos objeto del peldaño 5

La llamada recursiva actúa como una pila: imagina que la persona está arriba de la escalera, entonces baja hasta el peldaño 0, y después va recogiendo los objetos al subir de nuevo.

Cómo se estructura una función recursiva

La clave está en dos partes:

  • Condición base: evita llamadas infinitas (en este caso, cuando el peldaño es 0).
  • Llamada recursiva: repite el proceso con un número menor de peldaños.

Si quitamos la condición base:

function recogerSinFin(peldano) {
console.log(`En peldaño ${peldano}`);
recogerSinFin(peldano - 1);
}
recogerSinFin(5); // Causa un error de pila

Esto no se detiene nunca, provocando un error: Maximum call stack size exceeded. Lo que se conoce como stack overflow.

Cuándo puede tener sentido usar recursividad

Tiene utilidad cuando nos enfrentamos a tareas repetitivas y anidadas, como:

  • Recorrer estructuras tipo árbol (comentarios anidados, menús, carpetas)
  • Realizar operaciones secuenciales que pueden dividirse en pasos homogéneos
  • Procesar elementos desde una base hacia la parte superior, o al revés

Ejemplo de estructura anidada con subescaleras:

const escalera = {
peldano: 1,
objeto: 'Libro',
siguiente: {
peldano: 2,
objeto: 'Caja',
siguiente: {
peldano: 3,
objeto: 'Botella',
siguiente: null
}
}
};
function recorrerEscalera(nodo) {
if (!nodo) return;
console.log(`Peldaño ${nodo.peldano}: recogemos ${nodo.objeto}`);
recorrerEscalera(nodo.siguiente);
}
recorrerEscalera(escalera);

Este patrón permite recorrer estructuras de datos de forma limpia sin bucles anidados.

Limitaciones

La recursividad en JavaScript tiene un límite práctico: la pila de llamadas. Si hay demasiados peldaños, por ejemplo más de unos pocos miles, puede producirse un error de desbordamiento. Por eso, cuando se espera mucha profundidad, es más seguro optar por una versión iterativa.

Una versión iterativa equivalente al primer ejemplo sería:

function recogerObjetosIterativo(total) {
for (let i = 1; i <= total; i++) {
console.log(`Recogemos objeto del peldaño ${i}`);
}
}
recogerObjetosIterativo(5);

Conclusión

Usar recursividad nos permite expresar tareas paso a paso de forma compacta. Al usarla, debemos asegurarnos de incluir un caso base y considerar posibles alternativas iterativas si anticipamos una profundidad alta.