Could you explain me this freecodecamp recursion function, please?

Here's the code

function rangeOfNumbers(startNum, endNum) {
  return startNum === endNum
    ? [startNum]
    : rangeOfNumbers(startNum, endNum - 1).concat(endNum);
}

I understand that until startNum equals endNum it will recall itself, but the thing that I don't understand is where the value is stored?

Say for example it's rangeOfNumbers(3,6) So it's gonna be like this:

6-1
5-1
4-1

Right? And each time the numbers are added to the array and we get [3,4,5,6], but I don't understand how and where it stores this array.

If I'm not mistaken, concat merges two or more arrays, but there are no arrays.

I just want to have a full understanding of it. Otherwise, I won't remember it and won't be able to use it.


Solution 1:

As soon as the breaking condition is meet (startNum === endNum), an array is returned ([startNum]). Such object has a concat function which bubbles up another array and so on until the first call.

In resume: The array starts at the breaking condition and endNum is concatenated on each return value, which again, is an array.

Solution 2:

If I'm not mistaken, concat merges two or more arrays, but there are no arrays.

You are absolutely right about this. endNum is not an array. However, if you read further down in the docs, the argument supplied to concat can either be an array or value(s).

Parameters

valueN Optional

Arrays and/or values to concatenate into a new array. If all valueN parameters are omitted, concat returns a shallow copy of the existing array on which it is called. See the description below for more details.

Javascript functions are variadic by design, so it looks like the concat method takes advantage of this to accept individual arguments to append to a copy of the existing array.


I understand that until startNum equals endNum it will recall itself, but the thing that I don't understand is where the value is stored?

It may help if you write the function using explicit variable names

function rangeOfNumbers(startNum, endNum) {
  if (startNum === endNum) {
    return [startNum];
  }
  const currentRange = rangeOfNumbers(startNum, endNum - 1);
  return currentRange.concat(endNum);
}

As you can see, the value (or endNum) is stored inside the array returned by calling the function for the range [startNum, endNum - 1].

The trickiest part about recursion lies in the fact that you don't see where those intermediate values are stored, until as if by magic, we get to the base case and lo and behold, we have an array!

The answer is that the array returned by rangeOfNumbers(startNum, endNum - 1) is kept in stack memory until it needs to be returned. The discussion of stack vs heap will be quite off-topic here, but it is pretty much covered here:

What and where are the stack and heap?