Recursion: Full guide with JavaScript examples
Recursion confused me a bit, so I decided to write this...

Just a guy who loves to write code and watch anime.
Search for a command to run...
Recursion confused me a bit, so I decided to write this...

Just a guy who loves to write code and watch anime.
Nicely Done, Tiger! Awesome Read!
Spending 30 hours on a "3-4 hour" assignment is completely unfair, especially with those last-minute additions from HR. It sounds like they have zero respect for candidates' time. If they're this demanding and unrealistic in the interview process, imagine what it'd be like working there day-to-day. Honestly, you dodging this bullet might be a blessing in disguise. On to better opportunities, man!
Really comprehensive breakdown of recursion, man! Loved the part where you traced it back to nature—never really thought about it like that. Totally agree on the elegance factor, but yeah, I've learned the hard way about stack overflows, haha. Your point about when to consider recursion is spot-on. It's not the answer to every problem, but when you have tasks that naturally break down into smaller versions of themselves, it's often the cleanest way to go. Keep up the good work! https://gokutoapk.top/
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

As you know, I love blog-driven development.
I got a little bit confused about recursion when building a Linked List (data structure).
I ended up writing this piece for myself.
Enjoy the read.
Let's use the Inception analogy! Remember that movie scene where they dream within a dream and then... within another dream?
That's somewhat like recursion. In programming, it means a function that says, "I'm going to solve a part of this problem and let another 'mini-me' function handle the rest!" So, it calls itself until the problem is completely solved.
Back in the day, nature was showing off recursion with stuff like snowflakes and branching trees.
Fast forward, Fibonacci used recursion in a number sequence.
Fast forward even more, coders love recursion because it's like a magic trick for tough problems.
In short, recursion's been everywhere, from nature's patterns to today's code!
Problem Splitting: Sometimes, staring at a big problem is hard. But if you can make it into a "mini-version" of itself, then the problem becomes easier.
Elegance: For certain problems, recursion offers an elegant solution.
Data Structures: Structures like trees and graphs have a recursive nature. Imagine going through a family tree: "Who's the parent of the parent of the parent...?"
Base Case: This is your escape hatch. Without it, you're stuck in the recursive dream forever (or at least until the system crashes). It defines when to stop.
Recursive Case: The function is called here, but with a smaller or simpler piece of the problem.
Clean Code: For some problems, recursion provides a neat solution without many lines of code.
Tree & Graph Structures: Walking through trees (like the Document Object Model in web dev) is often naturally recursive.
Divide & Conquer: Helps to break down complex problems into smaller, more manageable ones.
Efficiency: Each function call consumes memory. A loop might handle the same task more efficiently.
Stack Overflow: Too much recursion can crash your program because it uses up all the space reserved for function calls.
Complexity: For newcomers, recursion can sometimes be a bit harder to wrap the head around compared to loops.
Imagine you're building software and face problems like navigating a deeply nested menu, searching through hierarchical data, or implementing certain algorithms.
If you notice that the task at hand can be broken down into simpler, repetitive steps, then consider recursion.
Every recursive call gets added to the Stack. The pattern it follows is "last in, first out". So the last function call will be the one first completing.
The key takeaway here is that every recursive call remains "paused" until all of the deeper recursive calls complete.
Each function call gets its own space in memory (often visualized as a stack frame). These stack frames hold function parameters, local variables, and the return address.
Let's say we have a countDown function where the base gets hit when the number becomes zero.
This is roughly how it would look like running till it hits the base case:
Stack:
countDown(3) --> still running (paused)
countDown(2) --> still running (paused)
countDown(1) --> still running (paused)
countDown(0) --> completed
Once the last function has been popped off the stack (the one that hit the base case), the next one runs. It recursively moves up and completes each function.
Let's say you're working on a file management system, something like Dropbox or Google Drive. Users can have folders, and within those folders, they can have more folders and files.
/**
* Recursively counts the total number of files in a directory and its subdirectories.
* @param {Directory} directory - The directory to start the count from.
* @returns {number} - Total number of files.
*/
function countFiles(directory) {
// Count the files in the current directory
let count = directory.files.length;
// Recursively count files in each subdirectory
for (let subdirectory of directory.subdirectories) {
count += countFiles(subdirectory);
}
return count;
}
Imagine you're developing a discussion platform similar to Reddit.
Users can leave comments, and other users can reply to those comments. This can go several layers deep (a comment on a comment on a comment, and so on). Now, you need a function that can print all comments and their replies in a structured way.
/**
* Recursively prints a comment and its replies.
* @param {Comment} comment - The comment to start printing from.
* @param {string} indent - Current level of indentation for visual structure.
*/
function printComment(comment, indent = '') {
// Print the current comment with the current level of indentation
console.log(indent + comment.text);
// Recursively print replies to this comment, increasing the indentation
for (let reply of comment.replies) {
printComment(reply, indent + '---');
}
}
The base case is essential in recursion. Without it, your recursive function will run indefinitely, leading to a stack overflow. It's the condition under which the function stops calling itself.
// Bad example
function countDown(number) {
console.log(number);
countDown(number - 1);
}
// Good example
function countDown(number) {
if (number <= 0) {
console.log("Done!");
return;
}
console.log(number);
countDown(number - 1);
}
Each recursive call should bring you one step closer to the base case. If you don't modify the inputs in a way that moves you towards the base case, you'll end up with infinite recursion.
// Bad example
function factorial(n) {
if (n === 0) return 1;
return n * factorial(n);
}
// Good example
function factorial(n) {
if (n === 0) return 1;
return n * factorial(n - 1);
}
It's important to remember that each recursive call gets its own execution context. Local variables aren't shared between calls.
// Bad example: Thinking that 'sum' will aggregate across recursive calls
function sumToN(n) {
let sum = 0;
if (n <= 1) return n;
sum += n + sumToN(n - 1);
return sum;
}
// Good example
function sumToN(n) {
if (n <= 1) return n;
return n + sumToN(n - 1);
}
Recursive functions often rely on return values of their recursive calls.
Ignoring or forgetting to use these can lead to incorrect results.
// Bad example: Ignoring the return value
function reverseString(str) {
if (str === "") return "";
const lastChar = str[str.length - 1];
reverseString(str.substring(0, str.length - 1));
return lastChar;
}
// Good example
function reverseString(str) {
if (str === "") return "";
const lastChar = str[str.length - 1];
// Make sure to return the recursive call
return lastChar + reverseString(str.substring(0, str.length - 1));
}
This however is necessary if you want something returned from the function.
Recursion is beautiful when used right.
The tricky part lies in understanding how the inner workings work.
I hope you enjoyed this.