Back to blog
Date
Welcome, JavaScript folks! Today, we delve into the interesting world of recursion, a programming concept that can both beguile and empower coders. We'll take a look at what recursion is, talk about the building blocks of recursion, common pitfalls and explore when recursion shines (and when it might not).
Recursion, in essence, is a function's ability to call itself. It creates a self-referential loop where the function breaks down a problem into smaller, similar subproblems, eventually reaching a base case that halts the recursion and provides the final answer. Imagine a set of Russian nesting dolls: the largest doll contains a smaller doll, which in turn contains an even smaller one, and so on, until you reach the tiniest doll. Recursion works similarly, with each function call representing a smaller version of the original problem.
Here are the building blocks to build a recursive algorithm:
Let's dive into some code examples to solidify these concepts.
We'll start with the example of summing a list of numbers using recursion.
function sumRecursive(list) {
if (list.length === 0) {
return 0; // Base case: empty list sum is 0
} else {
const firstElement = list[0];
const remainingList = list.slice(1);
return firstElement + sumRecursive(remainingList); // Recursive case
}
}
const numbers = [1, 2, 3, 4, 5];
const sum = sumRecursive(numbers);
console.log(sum); // Output: 15
Here's how we might achieve the same result using a for loop (iteration):
function sumIterative(list) {
let sum = 0;
for (const num of list) {
sum += num;
}
return sum;
}
const numbers = [1, 2, 3, 4, 5];
const sum = sumIterative(numbers);
console.log(sum); // Output: 15
This iterative approach is generally considered more efficient for simple tasks like summation. However, recursion shines in solving problems with a naturally recursive structure, as we'll see in the next example.
The Fibonacci sequence is a famous mathematical series where each number is the sum of the two preceding numbers (except the first two numbers, which are typically defined as 0 and 1). Let's see how recursion tackles this problem:
function fibonacciRecursive(n) {
if (n <= 1) {
return n; // Base case: 0 or 1
} else {
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2); // Recursive case
}
}
const number = 6;
const result = fibonacciRecursive(number);
console.log(result); // Output: 8
function fibonacciIterative(n) {
// Handle negative or zero input
if (n <= 0) {
return 0;
}
// Initialize first two Fibonacci numbers
let a = 0;
let b = 1;
// Iterate n-1 times (since the first two numbers are already defined)
for (let i = 2; i <= n; i++) {
let c = a + b;
a = b;
b = c;
}
// Return the nth Fibonacci number
return b;
}
// Example usage
console.log(fibonacciIterative(5)); // Output: 5
console.log(fibonacciIterative(10)); // Output: 55
Alright, we've reached the halfway point in our exploration of recursion in JavaScript. If your mind is a little blown right now, that's perfectly normal! Recursion can be a head-scratcher at first, but with practice, it becomes a powerful tool.
In the previous section, we saw how recursion can be used to solve problems like summing a list of numbers and generating the Fibonacci sequence. However, it's crucial to understand the potential pitfalls and trade-offs when using recursion compared to iterative approaches.
Here's an example of a potential stack overflow with recursion:
function wrongFactorial(n) {
if (n === 0) {
return 1;
} else {
return n * wrongFactorial(n); // We never change the value of n
}
}
wrongFactorial(5); // This will result in a stack overflow error
This function attempts to calculate the factorial of a number (3! = 3 * 2 * 1). However, it lacks a clause to change the value of n. This would cause the function to call itself infinitely, leading to a stack overflow error.
So, when should you choose recursion over iteration? Here are some ideas on that:
Ultimately, the choice between recursion and iteration depends on the specific problem you're trying to solve. Consider the trade-offs in terms of readability, performance, and potential for stack overflows.
Hopefully this was a helpful introduction or refresher on recursion! Definitely practice problems on platforms like Leetcode to solidify your understanding! Cheers!