I’ll give it a stab. Let’s see…
So we call the function countdown(5), and the first thing it checks is, is n less than one? If SO, create an empty array. In this case, it’s not, so it drops into the else section, and calls countdown(4), and assigns the return value to the variable arr. This part is key.
Now, with countdown(4), n=4 - so less than one? Nope. So drop to the else, and call countdown(3). Do it again, countdown(2). Again, countdown(1).
Finally, we call countdown(0). At this point, n=0. Is this less than one? Yup. So… we return an empty array. Where do we return that empty array? To the function just before this one - the function call countdown(1).
So now we’re unwrapping our recursive calls. Inside countdown(1) now, arr is an empty array, and n=1. The next thing we do here is arr.unshift(1), prepending n to that empty array, and returning arr (which is now [1]) to the next layer out - the function call countdown(2).
At this point, arr=[1] and n=2. Remember, we’re working our way back out of a whole bunch of nested function calls. So, still in the else branch of countdown(2), we arr.unshift(n), where n=2, so arr=[2,1], and return that value to countdown(3), which arr.unshifts(3), causing its own internal arr to be [3,2,1].
And we KEEP doing this, till we get back to our outermost function call, countdown(5). At that point, we’ve gone from an empty array, to an array with a single value, prepending and prepending, till we get to arr=[4,3,2,1] and n=5.
At this point, we do it one last time, making arr=[5,4,3,2,1], and we return that to our console.log(countdown(5) ) statement, displaying that final array.
Does that clear things up at all?