numbers.push(endNum) doesn’t happen until var numbers = rangeOfNumbers(startNum, endNum - 1) resolves, so we get a stack of function calls all waiting for the exit condition (endNum - startNum === 0) to be met.
For example, if we start with rangeOfNumbers(1, 3) this leads to us calling rangeOfNumbers(1, 2) which calls rangeOfNumbers(1, 1). That actually returns a value ([1]), so numbers inside rangeOfNumbers(1,2) is [1] and we push to it and it returns [1, 2]. Now that rangeOfNumbers(1, 2) has returned, the numbers in our original rangeOfNumbers(1, 3) is resolved to [1, 2]. We can push to it and return the final result.
Recursive calls is like setting up a bunch of dominoes. The exit condition is what tips the last one over.