La recursión es un concepto potente en programación que consiste en que una función se llame a sí misma. Puede ser un poco difícil de entender al principio, pero una vez que comprendes los fundamentos, se convierte en una herramienta muy valiosa para resolver problemas complejos. En este tutorial exploraremos la recursión en JavaScript con ejemplos fáciles de entender.
La recursión ocurre cuando una función se llama a sí misma, ya sea de forma directa o indirecta. Es similar a un bucle, pero implica dividir un problema en subproblemas más pequeños y manejables.
Empecemos con un ejemplo sencillo: una función de cuenta regresiva.
function countdown(num) {
// Base case
if (num <= 0) {
console.log('Blastoff!');
return;
}
// Recursive case
console.log(num);
countdown(num - 1);
}
// Call the function
countdown(5);
En este ejemplo:
num es menor o igual que 0, la función imprime «Blastoff!» y deja de llamarse a sí misma.num actual y se llama a sí misma con num - 1.Ahora veamos un ejemplo clásico de recursión: calcular el factorial de un número.
function factorial(n) {
// Base case
if (n === 0 || n === 1) {
return 1;
}
// Recursive case
return n * factorial(n - 1);
}
// Test the function
console.log(factorial(5)); // Output: 120
En este ejemplo:
n es 0 o 1, la función devuelve 1.n por el factorial de n - 1.Toda función recursiva debe tener al menos un caso base, una condición en la que la función deja de llamarse a sí misma. Sin un caso base, la recursión continuaría indefinidamente, lo que provocaría un desbordamiento de pila.
El caso recursivo define cómo la función se llama a sí misma con una versión más pequeña o más sencilla del problema.
Ventajas:
Desventajas:
La recursión es una técnica valiosa que puede simplificar problemas complejos al dividirlos en subproblemas más pequeños y manejables. Entender los casos base y los casos recursivos es fundamental para implementar soluciones recursivas eficaces en JavaScript.
Aprende más:
Tienes una pizzería y ofreces tres tipos de pizza:
Si los clientes quieren, pueden agregar una cantidad ilimitada de opciones extra: ya sea «ExtraSauce» por $1 o «ExtraToppings» por $2.
Tu tarea es escribir código que ayude al cliente a calcular cuánto le costará.
Recibes el nombre de la pizza como primer argumento y una cantidad ilimitada de opciones adicionales; calcula el precio de la pizza en dólares.
pizzaPrice('Margherita');
// => 7
pizzaPrice('Caprese', 'ExtraSauce', 'ExtraToppings');
// => 12
pizzaPrice(
'Caprese',
'ExtraToppings',
'ExtraToppings',
'ExtraToppings',
'ExtraToppings',
);
// => 17
Tu función se llama con una lista de PizzaOrders y debe devolver el precio total del pedido en dólares.
Cada PizzaOrder tiene una propiedad pizza, que es el nombre de la pizza, y una propiedad extras, que es la lista de opciones extra.
const margherita = new PizzaOrder('Margherita');
const caprese = new PizzaOrder('Caprese', 'ExtraToppings');
orderPrice([margherita, caprese]);
// => 18
Te darás cuenta de que no puedes escribir esto usando recursión, ya que una prueba con una cantidad enorme de pedidos lanzará un Maximum call stack size exceeded.
No te preocupes, esto es intencional: ¡intenta implementar esta función usando un bucle imperativo!
Tienes muchas opciones, como, entre otras, usar reduce o un bucle for.
Cuando el intérprete de JavaScript ejecuta el código JavaScript, lleva un registro de las funciones en las que ha entrado (que ha empezado a llamar) en una estructura de datos llamada «pila». Cuando la función retorna (termina), se elimina de la pila.
Sin embargo, esta pila tiene un tamaño limitado. El error más común es una función recursiva que nunca termina. Cada llamada se coloca en la pila, pero antes de que retorne, se coloca otra llamada en la pila.
function kaboom() {
kaboom()
}
kaboom()
// => RangeError: Maximum call stack size exceeded
La traza de la pila de este error muestra la misma línea una y otra vez, lo cual tiene sentido, porque la función se llama a sí misma. Aunque en la mayoría de los casos no tiene una aplicación práctica real, puedes averiguar qué tan alta puede llegar a ser esa pila.
let calls = 0;
function kaboom() {
calls +=1 ;
kaboom()
}
kaboom()
// => RangeError: Maximum call stack size exceeded
console.log(calls)
// => a number, generally higher than 10.000
Solo hay dos soluciones viables para un error de pila de llamadas causado por una función recursiva síncrona:
Regístrate en Exercism para aprender y dominar JavaScript con 37 conceptos159 ejercicios y mentoría humana real, todo gratis.