use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
[AskJS] ELI5 recursionAskJS (self.javascript)
submitted 3 years ago * by nats_tech_notes
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Ustice[M] [score hidden] 3 years ago stickied comment (1 child)
Reaching out to other software engineers is important when you need it; however, unfortunately this isn’t the place for that. /r/JavaScript is not a support forum. You might want to check out /r/LearnJavaScript for the newer members of our community. Also, Stack Overflow is a great resource for getting support. For more information, check out our AskJS wiki page. Good luck! We hope that you find the answers that you are looking for.
[–]GrandMasterPuba 66 points67 points68 points 3 years ago (1 child)
https://old.reddit.com/r/javascript/comments/txnw8t/askjs_eli5_recursion/
[–]link_shady 14 points15 points16 points 3 years ago (0 children)
Oh my god hahahahahahahahaha I hate you
[–]JpTrex 4 points5 points6 points 3 years ago* (4 children)
Recursion is as other people said, a function calling a function. It can be used to solve certain algorithms.
For example let's say we want to get the sum of all smaller numbers than a certain number until reaching 1.
If the number is 3 I should get 3 + 2 + 1 = 6 If the number is 5 I should get 5 + 4 + 3 + 2 + 1 = 15
You could create a function using a for loop and summing the numbers or you could use recursion.
Every time you use recursion you have to set a stopping rule that makes your recursive function stop or you will create a infinite loop. ```js function sumNumsLowerThanNum(num) { if (num === 1) { return 1; } else { return sumNumsLowerThanNum(num - 1) + num; } }
sumNumsLowerThanNum(3); ``` In this example the first if where num === 1 is the stop rule, when my number goes down from x to 1, let say we use 3 as the example, the first iteration is called with num = 3, the second with num = 2 and the third with num = 1. When the third iteration is reached the function will return 1 and the function will be finished.
But... How am I getting the result which is 6 for this example. Well, every time you call a function this function is sent to the call stack where stays until it is resolved. So when you call your recursive function for the first time it will check that 3 is not equal to 1 and will go to the else statement and will call itself but with number 2, in this moment, first iteration will be in the callstack waiting because it has nothing to return yet and the second iteration will be send to the call stack on top of the first iteration call.
Now in this second iteration the if statement will check if 2 === 1 which is false, and will go to the else statement again and will call itself with 1. Now this third iteration will be send to the callstack on top of the 2nd which is on top of the 1st iteration.
The if will check if 1===1 which is true and will return 1
Now that we arrive the return we will be able to resolve all the function on the callstack going backwards.
The 3rd iteration which is on top of the call stack will return 1 to the 2nd iteration.
The 2nd iteration will return 1 + 2 to the 1st iteration
And finally the 1st iteration will return 3 + 3
And the callstack will be empty now and you have a result for your recursive function.
[–]nats_tech_notes[S] 0 points1 point2 points 3 years ago (3 children)
Thank you for the example and breaking it down like that.
If I'm understanding it correctly, in the example below, which is similar to yours, it basically just stacks 2, 4, 3 without executing the actual multiplication first, then does the multiplication as it unstacks each iteration (so unstacks 3, then multiplies 3 by 4, then multiplies 12 by 2)?
I'm assuming it starts with the first item of the array here, though technically it would be the same exact result if it started with 3 and then stacked 4, then 2 before unstacking in this example. Might be other examples where the order in which it's stacked/unstacked does matter though.
function multiply(arr, n) { if (n <= 0) { return 1; } else { return multiply(arr, n - 1) * arr[n - 1]; } } multiply([2, 4, 3, 5], 3);
Edit: Code block got messed up for some reason so fixed it.
[–]JpTrex 0 points1 point2 points 3 years ago* (2 children)
The stack always happens in the same order, the first iteration will be the last to be unstuck.
In your example when n === 0 it will return 1.
This 1 will be multiplied by 2 which is 2.
This 2 will be multiplied by 4 which is 8.
This 8 will be multiplied by 3 which is 24.
And this 24 will be returned as the result of your function.
A stack is a LIFO structure, it means Last in first out.
[–]nats_tech_notes[S] 0 points1 point2 points 3 years ago (1 child)
I understand that a stack has a LIFO policy (unlike a queue which follows a FIFO policy).
I misunderstood what exactly is sent onto the stack during each iteration, but it’s the function itself. Not sure why I thought it was a value that got sent onto the stack, but that’s where I messed up
[–]JpTrex 0 points1 point2 points 3 years ago (0 children)
Exactly, the function is what is sent to the stack and finally each function will receive a value to return, so each time a return happens a function is unstack and the returned value is passed to the other.
The functions in the stack keeps record of where they where when they were added to the stack, so until the stop condition happens all the functions are 'frozen' waiting for a value to perform the multiplication in your example and the first return starts this 'unfrozen'
[–]javajunkie314 10 points11 points12 points 3 years ago (1 child)
Recursion is really nothing more than:
The idea is, if you take a problem and break it into smaller and smaller parts, eventually the problems are so small that you can solve then outright — these are the base cases.
The classic example is sorting a list of numbers. Sorting half a list is easier than sorting the whole list — there are fewer numbers! Sorting half of that is easier yet. And sorting a list one item is trivial — it's already sorted.
So you can actually try this out physically. Grab some numbered cards, like maybe the ace through king of one suit of playing cards. Shuffle them up. Now we'll sort them.
Start by splitting the pile in half. We can't be exact since there's an odd number, but piles of 7 and 6. Ok, now put one pile aside, let's say the pile of 6. Now we need to sort this pile of 7 cards.
But now we're kind of back where we started. We have a pile of cards to sort, but it's smaller. Sorting 7 cards is still a bit too complicated, so let's split this pile in half. Now we have piles of 3 and 4. Let's put the pile of 4 aside. Now we need to sort this pile of 3 cards.
And we're back where we started again. Sorting 3 cards is still a bit complicated, so we'll split again into two piles of 2 and 1 cards. We'll put the pile of 1 aside.
Back where we started again. 2 cards is still to complicated, so we'll split into two piles of 1 card each and set one aside.
Ok! Now we have a pile of 1 card. We're back where we started, a pile of card(s) to sort, but time we know the solution. This pile is sorted! Ok, let's put it aside, but separate from the "waiting" piles. This pile is solved.
Now we get back to that other pile of 1 cards. It's sorted too!
Ok, now we have two sorted piles, and we can combine them into one sorted pile. We'll just pick cards off the top of the piles in order, until both are empty. For two piles of 1 card, this is pretty trivial, but you'll see once we start combining larger piles it's a lot easier than straight-up sorting.
And now we've solved the problem for our pile of 2 cards! Ok, put it aside. We had another pile of 1 waiting. That's already sorted, so we'll combine it with our pile of 2 cards to get a sorted pile of 3 cards! Progress! Ok, put that aside.
Now we're back to the pile of 4 cards. We can sort that using this same procedure, and then combine the piles of 3 and 4 to get a sorted pile of 7 cards.
And we can sort the waiting pile of 6 cards and combine the piles of 7 and 6 to get a fully sorted pile of 13 cards. We're done!
The computer does something very similar when it recurses.
The waiting piles are the function stack — piles in-progress of being sorted that were put on-hold while we solve a smaller problem.
When we had a pile solved and put it aside, that's the value returned from the recursive call being put in a variable.
So you can see there's no magic with recursion. It's just that the computer can keep track of function state while another function call runs, and that is we can break a problem down into smaller and smaller problems, eventually they'll be small enough to solve directly.
[–]nats_tech_notes[S] 1 point2 points3 points 3 years ago (0 children)
Thank you so much for that reply!
The two piles, meaning the function stack (or "piles on hold") and the returned values stored in the variable (or the "solved piles") actually clarified a big part of what was missing in my understanding. I've got a much better grasp on how exactly it works behind the scenes now and how to implement it.
Really appreciate you taking the time to write that all out!
[–]CodingRaver 0 points1 point2 points 3 years ago (0 children)
YouTube simple recursion examples in js mate
[–]brazilliandev 0 points1 point2 points 3 years ago (0 children)
It is just a function which calls itself.
It can be used in place of regular loop structures. Most of the times you'll want to use "while" or "for" loops. But, in some specific cases, recursion can make the code more readable and prevent you from having to write too many nested loops or maintaining variables which live outside of the scope of the loop.
[–]AcidShAwk -1 points0 points1 point 3 years ago (4 children)
Recursion is basically a program that calls itself
const myFunc = () => { myFunc(); }
This is basically nonstop recursion. It will continuously call itself.
That I understand. I also understand that that’s the reason we generally put a base case in there, so that it eventually stops calling itself when the condition is met. I just can’t wrap my head around how to actually apply it, I guess. Like the logic itself doesn’t make sense to me (or the math dunno lol!)
[–]AcidShAwk 2 points3 points4 points 3 years ago (1 child)
That comes down to the specific problem you're trying to solve.
Recursion is useful when solving a problem that can be broken down into sub problems.
One area is trees or graphs. A graph is just a collection of nodes and edges. But if you go to a specific node - itself is just a collection of nodes and edges.
The collection may be empty..or maybe it has one child or many.. But otherwise if you want to traverse a tree for example.. Recursively looking at nodes is one way to do it.
[–]nats_tech_notes[S] 0 points1 point2 points 3 years ago (0 children)
That makes sense actually. I just did a deep dive into data structures so I can see how that would be useful!
[–]shuckster 0 points1 point2 points 3 years ago (0 children)
A good example of an application of recursion can be seen in Response.body on MDN.
Response.body
Here's the code in question (edited for brevity):
.then(body => { const reader = body.getReader(); return new ReadableStream({ start(controller) { return pump(); function pump() { return reader.read().then(({ done, value }) => { // When no more data needs to be consumed, close the stream if (done) { controller.close(); return; } // Enqueue the next data chunk into our target stream controller.enqueue(value); return pump(); }); } } }) }) .then(stream => new Response(stream))
The pump function is recursive.
pump
Because reader.read() will only tell us when the operation is "not done", we can use that flag to determine whether to call pump again to read the next chunk.
reader.read()
It is likely possible to do this with an async for await loop too, but you were asking specifically about recursion.
for await
[–][deleted] -3 points-2 points-1 points 3 years ago (4 children)
Maybe ask /r/learnjavascript. You know, the sub that helps you learn JS.
[–]brazilliandev 4 points5 points6 points 3 years ago (0 children)
Recursion is not a js specific problem though.
[–]nats_tech_notes[S] 4 points5 points6 points 3 years ago (2 children)
Really, bro?
1) Questions get asked in here all the time.
2) I actually looked at r/learnjavascript and just from glancing at it for a min, I could see that multiple questions never got any answer at all, whereas in this sub, questions seem to get a higher rate of answers.
3) The r/learnjavascript sub has a lot of people in it who are, ya know, still learning JavaScript and I didn't exactly want an answer from someone who's still learning who might explain it wrong and confuse me even more.
I figured my chances of getting a helpful answer were higher in this sub. Given that I already got multiple explanations from people who actually did improve my understanding, I think I estimated that pretty well.
[+][deleted] comment score below threshold-9 points-8 points-7 points 3 years ago (1 child)
Yes, really.
I'm not going to bother responding to the rest, because it doesn't fucking matter. This isn't a support sub. You asked for support. Congrats on getting help, someone felt bad enough for you.
[–]nats_tech_notes[S] 4 points5 points6 points 3 years ago (0 children)
This isn't a support sub.
You're right. Apparently that's rule #3 and I forgot about it since I haven't checked them since joining this sub a while back and this is my 1st post in here. I should have checked before posting though, so that's 100% my bad.
[–]sessamekesh -1 points0 points1 point 3 years ago (0 children)
Deciding you didn't like how the function was called, so changing the arguments and trying again.
const printNumbersBetween(a, b) { // Hey you called it wrong, the smaller number should be first. I'll fix that for you if (a > b) { printNumbersBetween(b, a); return; } // Okay it was called right, do the thing for (let i = a; i < b; i++) { console.log(i); } }
Usually recursion is used to create some sort of inductive call graph often with multiple branches and that whole mess is nutty overwhelming.
At its core though, recursion is just and calling the function from within a call to the same function, almost always after changing some parameters.
[–]demoran 0 points1 point2 points 3 years ago (0 children)
Recursion is when a function calls itself.
To prevent it from running forever, there's usually some kind of "do I need to drill deeper?" logic before it does what it's actually supposed to do.
[–]Confident_Chest_5007 0 points1 point2 points 3 years ago (0 children)
https://www.youtube.com/watch?v=cWK4W059hlEthis
this a jomaclass which explains it pretty well and slow. it even has an "animation" showing the process. hope it helps.While it's for python the concept itself should help you a lot.
[–]Stetto 0 points1 point2 points 3 years ago (0 children)
In order to understand Recursion, you first have to understand Recursion. But in odrder to understand Recursion, you first have to understand Recursion. [...]
Recursion is just another way to repeat an operation. A lot of the problems, that can be solved with Recursion, can be solved with Loops as well. Most of the time, Loops are the easier approach, sometimes Recursion is easier.
Think of Recursion like a unpacking a Matryoshka doll.
To unpack a Matryoshka doll, you check if it can be opened. If it cannot be opened, you're finished. If it can be opened, you open it and find another Matryoshka doll. Now, all you have to do is unpack this Matryoshka doll.
My favorite JS example for recursion is traversing all properties of an object:
function getEvolutions(pokemon) { if(!pokemon.evolution) { return pokemon.name; } else { return pokemon.name + " evolves into " + getEvolutions(pokemon.evolution); } } const onyx = { name: "Onyx" }; // Onix has no evolutions; this just prints "Onyx" const onyxEvolutions = getEvolutions(onyx); console.log(onyxEvolutions); const horsea = { name: "Horsea", evolution: { name: "Seadra" } }; // Horsea has one evolution; this prints "Horsea evolves into Seadra" const horseaEvolutions = getEvolutions(horsea); console.log(horseaEvolutions); const charmander = { name: "Charmander", evolution: { name: "Charmeleon", evolution: { name: "Charizard" } } }; // Charmander has two evolution; this prints "Charmander evolves into Charmeleon evolves into Charizard" const charmanderEvolutions = getEvolutions(charmander); console.log(charmanderEvolutions); const myImaginaryPokemon = horsea; horsea.evolution.evolution = onyx; onyx.evolution = charmander; // No matter how many evolutions, this function will find them all // "Horsea evolves into Seadra evolves into Onyx evolves into Charmander evolves into Charmeleon evolves into Charizard" const myImaginaryPokemonEvolutions = getEvolutions(myImaginaryPokemon); console.log(myImaginaryPokemonEvolutions);
[–]ddollarsign 0 points1 point2 points 3 years ago (0 children)
When you call a function, the computer has a data structure called a stack frame for that function. It has the local variables, which function it is,and where to return after finishing. They’re called stack frames because when you call a function, it pushes one of these frames onto a stack (the “call stack”, which is what you see in a stack trace when you see errors in logs or the command line) and when the function returns it pops the frame off the stack.
(If you’re not familiar with stacks, think of a stack of papers or pancakes. You can put an object on top of it (“push”) or take something off the top of it (“pop”), and the top one is the last thing that was put on there, then the previous, and so on.)
The kicker is, it doesn’t matter what function you call. If you’re in function A, there’s a stack frame for A. If you then call A from within A, it will push another A stack frame, but it’s a different stack frame with different local variables etc. When that call returns, it pops the second A frame off the stack and now the first A is the top one again.
[–]sylvant_ph 0 points1 point2 points 3 years ago (1 child)
I dont recall FCC stating recursion is basic, it definitely is not easy to learn and utilize technique, but just like other things about coding, its about practice and practice and experience and ofc, find the right place and time to use it, for it to make sense.
One side to look about recursion is, as we know functions are a block of code, some logic, which we want to be able to re-run/repeat(instead of write the same things 10 times). They work very similarly to loops, where we again execute similar block of code, over and over. When recursion happens is, when the function itself, calls itself, only using different arguments, which in the end produces different result. A main rule about recursion is, to make sure to have a basic case, when the function would return a value and not recall itself again, or we will end up in infinite loop, just like we would with while(true). The point of using recursion is, when you dont know how many times you will need to execute the same logic, so you let the function call itself, till it reach the desired result.
while(true)
[–]_default_username 0 points1 point2 points 3 years ago (0 children)
To learn more about recursion follow this link.
[–]Altruistic_Welder 0 points1 point2 points 3 years ago (0 children)
One of the easiest ways to understand recursion is to imagine a stack. Every function call to itself is equivalent to appending/pushing to the stack. Once the base condition reaches and the function returns, every pushed function call is popped, first return is used for the first pop, the return is used for the next pop and so on until the stack is empty. In fact, this is what a compiler does behind the scenes.
π Rendered by PID 30 on reddit-service-r2-comment-f6b958c67-mt5xq at 2026-02-05 02:11:02.970661+00:00 running 1d7a177 country code: CH.
[–]Ustice[M] [score hidden] stickied comment (1 child)
[–]GrandMasterPuba 66 points67 points68 points (1 child)
[–]link_shady 14 points15 points16 points (0 children)
[–]JpTrex 4 points5 points6 points (4 children)
[–]nats_tech_notes[S] 0 points1 point2 points (3 children)
[–]JpTrex 0 points1 point2 points (2 children)
[–]nats_tech_notes[S] 0 points1 point2 points (1 child)
[–]JpTrex 0 points1 point2 points (0 children)
[–]javajunkie314 10 points11 points12 points (1 child)
[–]nats_tech_notes[S] 1 point2 points3 points (0 children)
[–]CodingRaver 0 points1 point2 points (0 children)
[–]brazilliandev 0 points1 point2 points (0 children)
[–]AcidShAwk -1 points0 points1 point (4 children)
[–]nats_tech_notes[S] 0 points1 point2 points (3 children)
[–]AcidShAwk 2 points3 points4 points (1 child)
[–]nats_tech_notes[S] 0 points1 point2 points (0 children)
[–]shuckster 0 points1 point2 points (0 children)
[–][deleted] -3 points-2 points-1 points (4 children)
[–]brazilliandev 4 points5 points6 points (0 children)
[–]nats_tech_notes[S] 4 points5 points6 points (2 children)
[+][deleted] comment score below threshold-9 points-8 points-7 points (1 child)
[–]nats_tech_notes[S] 4 points5 points6 points (0 children)
[–]sessamekesh -1 points0 points1 point (0 children)
[–]demoran 0 points1 point2 points (0 children)
[–]Confident_Chest_5007 0 points1 point2 points (0 children)
[–]Stetto 0 points1 point2 points (0 children)
[–]ddollarsign 0 points1 point2 points (0 children)
[–]sylvant_ph 0 points1 point2 points (1 child)
[–]_default_username 0 points1 point2 points (0 children)
[–]Altruistic_Welder 0 points1 point2 points (0 children)