关于JS中递归示例的初学者问题



我是一个初学者,正在学习JS教程,在这个递归函数示例中,我很难理解语句执行的顺序:

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

我假设,每次到达const countArray = countup(n - 1);行时,它都会用递减的n将执行返回到第1行。这将解释输出数组从1开始向上,而n正在向下。但在这种情况下,函数不应该只返回空数组[]吗?因为n会降到1以下,满足第一个if,并在任何东西被推入countArray(else(之前终止?**尝试在谷歌上搜索断点的使用来查看实际流,但只看到它们在非循环中的使用

让我们简单地假设每个函数调用及其所有信息都将存储在一个堆栈中。注意,堆栈是后进先出法。

因此,在您的代码中,countup(5)将被调用并存储在stack[0]中。

然后在else条件中,它再次被称为countup(4)。这将暂停执行countup(5),并且countup(4)将被存储在stack[1]中。

就像这样,直到n<1计数将被调用一个较低的值并存储在堆栈中。

在所有调用结束时,堆栈将像

- stack[4]    countup(1)
- stack[3]    countup(2)
- stack[2]    countup(3)
- stack[1]    countup(4)
- stack[0]    countup(5)

现在将开始从堆栈中弹出。由于堆栈是后进先出法,所以堆栈顶部的元素将被弹出。Popped表示您正在从堆栈中删除该元素。

则首先弹出countup(1)并完成其执行。那就是countArray.push(1)

countup(2)将位于堆栈的顶部。因此,弹出countup(2)并完成其执行countArray.push(2)

就像这样,则弹出CCD_ 19并完成其执行CCD_。弹出countup(4)并完成其执行countArray.push(4(。则弹出CCD_ 22并完成其执行CCD_。

最后返回整个数组。

*我已经简单地描述过了。真正的幕后执行还有很多事情要做,还有很多其他的术语需要了解。您可以查看这篇描述递归如何在JS 中工作的文章

我不知道您是否熟悉"散布";语法,但如果else子句的主体写得简单:,可能会更容易了解发生了什么

return [...countUp(n - 1), n];

这意味着它是通过取countUp(n - 1)并在末尾添加元素n得到的数组。您显示的代码做的是相同的,只是方式略有不同。希望从这个描述中可以清楚地看到函数为什么会这样做——但如果它仍然不是,请注意:

  • countUp(0)为空
  • 因此,countUp(1)由一个空数组组成,末尾有一个额外的1,因此单例数组[1]
  • countUp(2)是上面的,末尾有一个2[1, 2]

等等。