Why does recursion reverse itself?

function countUp(n) {
  if (n < 1) return [];
  const array = countUp(n-1)
  array.push(n)
  return array;
}

console.log(countUp(3))

Let’s look at how this is evaluated.

Inside the console log we call countUp with n=3 so we need to evaluate that. To evaluate it we’ll need to run all the lines of the function.

// lines to run for countUp(3)
  if (3 < 1) return []; // 3 is not less than 1 so skip this
  const array = countUp(3-1) // pause here!
  array.push(3)
  return array;

But in the middle of evaluating that call, we call another function, countUp(2), so we’ll need to evaluate that before continuing on.

// lines to run for countUp(2)
  if (2 < 1) return []; // 2 is not less than 1 so skip this
  const array = countUp(2-1) // pause here!
  array.push(2)
  return array;

But in the middle of evaluating that call, we call another function, countUp(1), so we’ll need to evaluate that before continuing on.

// lines to run for countUp(1)
  if (1 < 1) return []; // 1 is not less than 1 so skip this
  const array = countUp(1-1) // pause here!
  array.push(1)
  return array;

But in the middle of evaluating that call, we call another function, countUp(0), so we’ll need to evaluate that before continuing on.

// lines to run for countUp(0)
  if (0 < 1) return []; // 0 is less than one so return here
  // skip the lines below because we've already returned
  const array = countUp(0-1)
  array.push(0)
  return array;

The call to countUp(0) returns [], so now we can continue where we left off with countUp(1).

// lines to run for countUp(1)
  if (1 < 1) return [];
  const array = countUp(1-1) // continue evaluation from here
  array.push(1) // array is now [1]
  return array; // return [1]

The call to countUp(1) returns [1], so now we can continue where we left off with countUp(2).

// lines to run for countUp(2)
  if (2 < 1) return [];
  const array = countUp(2-1) // continue evaluation from here
  array.push(2) // array is now [1, 2]
  return array; // return [1, 2]

The call to countUp(2) returns [1, 2], so now we can continue where we left off with countUp(3).

// lines to run for countUp(3)
  if (3 < 1) return [];
  const array = countUp(3-1) // continue evaluation from here
  array.push(3) // array is now [1, 2, 3]
  return array; // return [1, 2, 3]

Now the return value of countUp(3), [1, 2, 3], is logged to the console.

2 Likes