The problem is that you do not pass on the array to the recursive call, so each recursive execution creates a new, empty array. As a consequence, it does not return the array that had a value pushed to it, but the new, empty one that is coming back from the recursive calls.

Secondly, you never push value 1 to the array. So it would be better to stop the recursion at 0 instead of 1.

So taking those two fixes, you get this:

function countdown(n, newArr=[]) {
    if (n <= 0) {
        return newArr;
    }
    newArr.push(n);
    return countdown(n - 1, newArr)
}

console.log(countdown(5));

Your alternative solution is clean, because it does not need to pass an array as argument. It uses the returned array to add the next value to it (in front of it). It would have my preference.

To understand how it works, print out the intermediate values:

function countdown(n) {
  if (n < 1) {
    console.log("At the end of recursion. Creating and returning an empty array.");
    return [];
  } else {
    const arr = countdown(n - 1);
    console.log("Got the following array back from the recursive call:");
    console.log(JSON.stringify(arr));
    arr.unshift(n);
    console.log("Prefixing it with " + n + " and returning the result:");
    console.log(JSON.stringify(arr));
    return arr;
  }
}

var result = countdown(5);

Answer from trincot on Stack Overflow
🌐
freeCodeCamp
forum.freecodecamp.org › guide
freeCodeCamp Challenge Guide: Use Recursion to Create a Countdown - Guide - The freeCodeCamp Forum
December 3, 2019 - Use Recursion to Create a Countdown Solutions Solution 1 (Click to Show/Hide) function countdown(n) { if (n < 1) { return []; } else { const arr = countdown(n - 1); arr.unshift(n); return arr; }
Top answer
1 of 4
4

The problem is that you do not pass on the array to the recursive call, so each recursive execution creates a new, empty array. As a consequence, it does not return the array that had a value pushed to it, but the new, empty one that is coming back from the recursive calls.

Secondly, you never push value 1 to the array. So it would be better to stop the recursion at 0 instead of 1.

So taking those two fixes, you get this:

function countdown(n, newArr=[]) {
    if (n <= 0) {
        return newArr;
    }
    newArr.push(n);
    return countdown(n - 1, newArr)
}

console.log(countdown(5));

Your alternative solution is clean, because it does not need to pass an array as argument. It uses the returned array to add the next value to it (in front of it). It would have my preference.

To understand how it works, print out the intermediate values:

function countdown(n) {
  if (n < 1) {
    console.log("At the end of recursion. Creating and returning an empty array.");
    return [];
  } else {
    const arr = countdown(n - 1);
    console.log("Got the following array back from the recursive call:");
    console.log(JSON.stringify(arr));
    arr.unshift(n);
    console.log("Prefixing it with " + n + " and returning the result:");
    console.log(JSON.stringify(arr));
    return arr;
  }
}

var result = countdown(5);

2 of 4
2

You need to hand over the result array for the recursive call. And you need to check if no value is left, ten return the result array.

function countdown(n, result = []) {
    if (n < 1) return result;
    result.push(n);
    return countdown(n - 1, result);
}

console.log(countdown(5));

As another approach, you could return an array and for the exit condition take the final value, otherwise take n and the spreaded result of the recursive call.

function countdown(n) {
    if (n < 1) return [];
    return [n, ...countdown(n - 1)];
}

console.log(countdown(5));

Discussions

Basic JavaScript: Use Recursion to Create a Countdown
Tell us what’s happening: Hello there, this is my first post. The test says I’m wrong, whereas I’m pretty sure that i’m being right, i already tested it in another editor and it work. So i don’t know where is the probleme, maybe it has something to do with the way it’s tested. More on forum.freecodecamp.org
🌐 forum.freecodecamp.org
1
0
October 16, 2019
javascript - Recursive countdown timer - Stack Overflow
I'm trying to create a javascript counter that starts at 25 minutes and ends at 0. the idea is to show the minutes/seconds as a countdown clock on the page (my target div is called 'txt'). But I'm ... More on stackoverflow.com
🌐 stackoverflow.com
May 22, 2017
Basic JavaScript: Use Recursion to Create a Countdown
  1. That if clause is checking whether the argument is less than 1. If you’ve passed in 5, that’s more than 1 so the if block is never executed.

  2. This is the recursion part. The thing to think about is that the code block will recur until the if clause is met, which returns an empty array. So the first line of the else cause is what will execute recursively. This returns an empty array which then has all of the numbers pushed into it as the blocks of code from each prior recursion get executed.

I’m not a huge fan of this sort of recursive pattern because it values brevity over clarity. In most real world circumstances, the marginal reduction in computational overhead will be of no benefit if others working on the code have a hard time understanding it.

More on reddit.com
🌐 r/FreeCodeCamp
8
3
May 31, 2020
javascript - How does recursion work in a Countdown function - Stack Overflow
I'm learning a bit of JavaScript, but I'm having hard time understanding the lesson on FreeCodeCamp about the recursion countdown (link). In the lesson, there this initial example. But I'm confused... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Reddit
reddit.com › r/learnprogramming › using recursion to create a countdown in javascript
r/learnprogramming on Reddit: Using recursion to create a countdown in Javascript
July 21, 2021 -

Hi guys, I am stuck on a very simple recursion problem where I am asked to use recursion to count down from n and log each number. The prompt is as follows:

"Write a recursive function that accepts a positive integer n as an input and logs every number from n (inclusive) to 0 (exclusive) to the console"

And here is my attempt:

function countDown (n) {

//base case

if (n <= 0) { return 0}

// recursive call

else { countDown (n-1)

console.log(n)

}

Trying to figure out where I am going wrong here and I appreciate any feedback. Thanks!!!

🌐
DEV Community
dev.to › rthefounding › using-recursion-to-create-a-countdown-59gp
Using Recursion to Create a Countdown - DEV Community
April 25, 2021 - For example, calling this function with n = 5 should return the array [5, 4, 3, 2, 1]. Your function must use recursion by calling itself and must not use loops of any kind. ... function countdown(n) { if (n < 1) { return []; } else { var ...
🌐
Codelikethis
codelikethis.com › lessons › javascript › recursion
Recursion - Code Like This
The simplest form of recursion uses a counter; in this example we are counting down the seconds until a rocket launches. function countdown(seconds) { if (seconds == 0) { console.log("Blastoff!"); } else { console.log("" + seconds + "..."); let nextCount = seconds - 1; countdown(nextCount); ...
🌐
YouTube
youtube.com › teachtolearn
How to Use Recursion to Create a Countdown in JavaScript - YouTube
By watching this video, you will learn how to use recursion to create a countdown in JavaScript. Thank you so much for watching, and don't forget to leave a ...
Published   April 14, 2021
Views   6K
🌐
DEV Community
dev.to › naveenkolambage › create-a-countdown-using-recursion-freecodecamp-notes-1k2m
Create a countdown using recursion (FreeCodecamp notes) - DEV Community
September 22, 2022 - function countdown(n, newArr=[]) { if (n <= 0) { return newArr; } newArr.push(n); return countdown(n - 1, newArr) } console.log(countdown(5)); So thats how you pass the argument array with its elements in the recursive function.
Find elsewhere
🌐
OneCompiler
onecompiler.com › javascript › 3wmgqckn2
Freecodecamp Basic JavaScript: Use Recursion to Create a Countdown - JavaScript - OneCompiler
// Only change code below this line function countdown(n){ if (n < 1) { return []; } else { const countArray = countdown(n - 1); // console.log("Before Shift: ", countArray) countArray.unshift(n); console.log("After Shift: ", countArray) return countArray; } } // Only change code above this line console.log(countdown(7)); ... Write, Run & Share Javascript code online using OneCompiler's JS online compiler for free.
🌐
JavaScript Tutorial
javascripttutorial.net › home › javascript tutorial › javascript recursive function
JavaScript Recursive Function
November 15, 2024 - Let’s take some examples of using recursive functions. Suppose that you need to develop a function that counts down from a specified number to 1. For example, to count down from 3 to 1: ... function countDown(fromNumber) { console.log(fromNumber); } countDown(3);Code language: JavaScript (javascript)
🌐
Medium
medium.com › @zfrisch › understanding-recursion-in-javascript-992e96449e03
Understanding Recursion in JavaScript | by Zak Frisch | Medium
November 28, 2016 - When constructing a recursive function in JavaScript there must always be a Leave Event. What is a Leave Event? It is any control statement that allows the function to exit the recursive loop.
🌐
Reddit
reddit.com › r › FreeCodeCamp › comments › gtf4lh › basic_javascript_use_recursion_to_create_a
r/FreeCodeCamp - Basic JavaScript: Use Recursion to Create a Countdown
May 31, 2020 -

hello everyone,I'm having a hard time understanding how the code from this exercise works, i tried using debugger but I got more confused

function countup(n) {if (n < 1) {return [];} else {const countArray = countup(n - 1);countArray.push(n);return countArray;}}console.log(countup(5)); // [ 1, 2, 3, 4, 5 ]

what I understand so far is that the function countup(5) gets executed then the recursion keeps happening till n=0

if (n < 1) {return [];}

now we have an empty array and that's all I understand😅

1.why am I not kicked out of the if statement after that, how does the function keeps executing??

2.the function then start pushing the numbers incrementally, what causes the increment here?? Also when I the debugger I noticed that the function would hit the last curly bracket and then jump back tocountArray.push(n); how does that happen .. any clarification would be appreciated

Top answer
1 of 3
2
  1. That if clause is checking whether the argument is less than 1. If you’ve passed in 5, that’s more than 1 so the if block is never executed.

  2. This is the recursion part. The thing to think about is that the code block will recur until the if clause is met, which returns an empty array. So the first line of the else cause is what will execute recursively. This returns an empty array which then has all of the numbers pushed into it as the blocks of code from each prior recursion get executed.

I’m not a huge fan of this sort of recursive pattern because it values brevity over clarity. In most real world circumstances, the marginal reduction in computational overhead will be of no benefit if others working on the code have a hard time understanding it.

2 of 3
2

the return happens when n<1.

As far as how the recursion works, it happens on the first line of the else block. You create a variable and assign it the value of executing countup with (n-1). You can't go to the next line until this line has resolved.

So what happens? you run another instance of countup, this time with n-1. If that n is now less than 1, it'll return the empty array, and you don't hit the else block, meaning you don't execute countup again.

At that point the countup inside of your countup returns []. You do get kicked out of the if statement, but it's the inside countup, meaning there's still the outside countup, where you were figuring out what countarray is. Now that we know that countArray is [], we can push n to that array and return it.

Top answer
1 of 4
5

Realise that every execution of countup will have its own n and countArray variables.

It may help to visualise it. Each execution context is visualised as a "box". The variables in the outer boxes will still be there, when a function call returns.

The outermost box is the execution context that is created by the initial call: countup(5):

// n is 5 and does not change
const countArray = countup(n - 1);
+-------------------------------------------------------------------------------+
|  // n is 4 and does not change                                                |
|  const countArray = countup(n - 1);                                           |
|  +-------------------------------------------------------------------------+  |
|  |  // n is 3 and does not change                                          |  |
|  |  const countArray = countup(n - 1);                                     |  |
|  |  +-------------------------------------------------------------------+  |  |
|  |  |  // n is 2 and does not change                                    |  |  |
|  |  |  const countArray = countup(n - 1);                               |  |  |
|  |  |  +-------------------------------------------------------------+  |  |  |
|  |  |  |  // n is 1 and does not change                              |  |  |  |
|  |  |  |  const countArray = countup(n - 1);                         |  |  |  |
|  |  |  |  +-------------------------------------------------------+  |  |  |  |
|  |  |  |  |  // n is 0 and does not change                        |  |  |  |  |
|  |  |  |  |  return []; // the if-block is executed because n < 1 |  |  |  |  |
|  |  |  |  +-------------------------------------------------------+  |  |  |  |
|  |  |  |  // countArray is []                                        |  |  |  |
|  |  |  |  countArray.push(n); // n is still 1                        |  |  |  |
|  |  |  |  return countArray; // returns [1]                          |  |  |  |
|  |  |  +-------------------------------------------------------------+  |  |  |
|  |  |  // countArray is [1]                                             |  |  |
|  |  |  countArray.push(n); // n is still 2                              |  |  |
|  |  |  return countArray; // returns [1, 2]                             |  |  |
|  |  +-------------------------------------------------------------------+  |  |
|  |  // countArray is [1, 2]                                                |  |
|  |  countArray.push(n); // n is still 3                                    |  |
|  |  return countArray; // returns [1, 2, 3]                                |  |
|  +-------------------------------------------------------------------------+  |
|  // countArray is [1, 2, 3]                                                   |
|  countArray.push(n); // n is still 4                                          |
|  return countArray; // returns [1, 2, 3, 4]                                   |
+-------------------------------------------------------------------------------+
// countArray is [1, 2, 3, 4]
countArray.push(n); // n is still 5
return countArray; // returns [1, 2, 3, 4, 5]
2 of 4
1

You can just add some logging to visualize what is happening:

function countup(n) {
  if (n < 1) {
    console.log('n = %d, returning empty array', n);
    return [];
  } else {
    console.log('n = %d, calling countup(%d - 1)', n, n);
    const countArray = countup(n - 1);
    console.log('n = %d, countArray is %s', n, JSON.stringify(countArray))
    console.log('n = %d, pushing n onto array', n);
    countArray.push(n);
    console.log('n = %d, returning %s', n, JSON.stringify(countArray));
    return countArray;
  }
}
console.log(countup(5));

Top answer
1 of 4
5

Why is the array declared as a constant and assigned to the recursion call?

It is not. The array is variable. Every call to this function will return a new array. No arrays get "overwritten". const in JavaScript is merely used to declare a constant variable which has lexical scope (that is, the variable arr ceases to exist after return arr) and is constant (can't be mutated / assigned to).

I get the unshifting of the current value, but why is it declared after the recursive call? Shouldn't it be positioned before (one line above) so as to unshift the value before the function loops itself?

You can't position it above since the recursive call is required to obtain arr in the first place. After you have counted down from n-1 to 1, you must prepend n at the first position, which is what unshift does.

Similarly, why is the full final array returned within the else loop? Shouldn't it be better returned outside, or on the base condition above, so as to not be returned every time the function loops?

There is no such thing as an "else loop". The reason for returning the array there as well is that you want countdown(n) to return the array it has just generated, using the array countdown(n-1).

As it is, my understanding is that when n reaches 0, the loop should return an empty array, and not the full array that has been created with the recursion.

That's exactly what if (n < 1) return []; does.


That said, for the task at hand the recursive implementation given is highly suboptimal. First of all, you don't need the else since return will exit the function anyways:

function countdown(n) {
  if (n < 1) return [];

  const arr = countdown(n - 1);
  arr.unshift(n);
  return arr;
}

second, this is most readable (and performant) as a simple for loop:

function countdown(n) {
  const arr = Array(n)
  for (let i = 0; i < n; i++) arr[i] = n - i;
  return arr;
}

(bonus: the array size being known ahead of time can be leveraged using the Array constructor to prevent JS having to resize the Array as you push elements).

third, the current implementation has a quadratic time complexity of O(n²) because arr.unshift is a linear-time operation which is applied n times to arrays of length 0 to n-1.

Recursion is extremely useful when you need the stack (f.E. in a depth-first traversal). Creating a countdown doesn't require a stack. This is not using but rather abusing recursion to implement a highly suboptimal algorithm. If you - for whatever reason (perhaps you are forced to use a purely functional language that has no loops, only recursion?) - wanted to replace the perfectly fine for loop with a recursive call at all cost, simply use tail recursion and lexical scope (closures):

function countdown(n) {
  const arr = [];
  function loop(n) {
    if (n < 1) return;
    arr.push(n);
    loop(n-1);
  }
  loop(n);
  return arr;
}

or if you don't like closures, what about an optional arr parameter? This allows turning the recursion around since the caller now has the arr before the callee and can thus append its number before subsequent recursive calls do the same:

function countdown(n, arr = []) {
  if (n < 1) return arr;
  arr.push(n);
  countdown(n - 1, arr);
  return arr;
}

same result, but (IMO) cleaner, and most importantly, significantly faster code. Try running all these functions on n = 1e6 and you will see that the freeCodeCamp one fails to complete in a reasonable timeframe whereas the other ones finish almost instantly.

2 of 4
4

It might help to clarify how the code is working a little. Hopefully, the explanation clears up your questions a bit. Let's start with the most basic case:

countdown(0) - When you call countdown(0) your if-block runs and returns an empty array []. So we see that countdown(0) outputs []. This is the base case.

Next, let's imagine we call the function again, this time as:

countdown(1) - In this scenario the else block runs. We see that it calls countdown(0), which means the interpreter executes the function again, passing n as 0. Above we saw what happens when countdown(0) is called, it returns an empty array [], so that's what gets assigned to arr within the else block. We then unshift n (which is 1 here) onto this empty array, which adds 1 to the start of the array stored in arr. This is then returned. So we say that countdown(1) outputs [1].

Now let's see what happens if we were to call the function again with 2:

countdown(2) - Again, the else block runs, triggering a call to countdown(1). We saw above what occurs when this is called, we get back an array with [1], which is stored in the local variable arr, and we then .unshift(2) so that 2 is added to the beginning of the array which we then return. So we see that countdown(2) returns [2, 1].


When thinking about recursion, it can be helpful to think of it as breaking down your input until it's at a small enough value that it can't be broken down anymore (your base case). Once you hit that, you work your way back up, stitching together your previous calls now that you have "solved" the sub-problems.

To answer your questions more directly:

  1. arr is assigned to the recursive call so that we can build upon the results it returned. If countdown(1) returns [1], then we can build onto that result by storing it in arr and unshift 2 onto it to calculate countdown(2). It could have been made let, but const is commonly used if the variable doesn't need to be reassigned. We don't want to move arr outside of the function as then calling countdown() multiple times will modify the same global array. You would also need to change your code so that we can gradually "build-up" the result by further recursive calls if you did that also, which is more of a "loop mindset" than a "recursive mindset".

  2. Moving the .unshift() component before the recursive call wouldn't work as you wouldn't have anything to unshift to. The recursive call is what provides you with the array result of countdown(n-1) so that you can build onto that later by using .unshift().

  3. Returning your array in the else block is what allows you to obtain results when n is greater than 0. In the countdown(1) example above, we need to return arr so that it outputs [1]. This needs to be in the else block because we're returning arr which is defined in that else-block (and hence can't be accessed outside of it).

🌐
CopyProgramming
copyprogramming.com › howto › javascript-recursion-to-create-a-countdown-code-example
An Example of Countdown Code Using Recursion in Javascript - Javascript
June 7, 2023 - function countdown(n){ if(n == 0){ // stop the function at 0 so it will not be included in the array return []; } // concat the value of n as an array with the value less than it return [n].concat(countdown(n - 1)) } console.log(countdown(5)); The issue with your solution is that the array ...
🌐
Programiz
programiz.com › javascript › recursion
JavaScript Recursion (with Examples)
In the above example, we have a function counter() that accepts the argument count, which is the starting point for our countdown till 1. The counter() function first displays count then checks if the value of count is greater than 1 with count > 1. If count > 1 evaluates to true, the program decreases the value of count and calls counter() with the new value of count (recursion).
🌐
Codesmith
codesmith.io › blog › introduction-to-recursion-in-javascript
Demystifying Recursion in JavaScript: A Beginner’s Guide
November 21, 2025 - Remember, each recursive call must bring your function closer and closer to the base case, so it eventually knows when to stop running. That means the input passed into each recursive call has to change in a way that moves you toward the stopping condition. In our countdown example, we did this by decrementing n by 1 on each recursive call, countdown(n - 1)