我正在学习一些 JavaScript,但我很难理解 FreeCodeCamp 上关于递归倒计时 (link) 的课程。
在课程中,有这个初始示例。但我对它的运作方式感到困惑:
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countup(n - 1);
countArray.push(n);
return countArray;
}
}
console.log(countup(5));
我看到这个函数执行的步骤(按顺序),如下所示:
n
(以 5 开头)大于 1,因此转到 else
语句。else
语句中,我将分配一个常量 (countArray
) 来执行 countup(n - 1)
,它
是 4。countArray.push(n)
,因此它将把 4 推入一个数组中。return countArray
,即 4。n==0
,在这种情况下
函数结束返回一个空数组。我知道这不是它的工作原理,我只是在“描述”我的菜鸟思维如何看待这个递归函数。
我看了练习的解决方案和其他人的解释,但我不明白为什么这个函数不能像我描述的那样工作,以及为什么到达n==0
后,它开始填满一个数组从 1 到 5。
我想了解这一点。
答案 0 :(得分:4)
意识到每次执行 countup
都会有自己的 n
和 countArray
变量。
它可能有助于形象化。每个执行上下文都可视化为一个“盒子”。当函数调用返回时,外部框中的变量仍然存在。
最外面的框是由初始调用创建的执行上下文: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]
答案 1 :(得分:1)
你可以添加一些日志来可视化正在发生的事情:
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));
答案 2 :(得分:0)
如果有帮助,这里是每个函数调用内部的数组:
Array: 1 N: 1
Array: 1,2 N: 2
Array: 1,2,3 N: 3
Array: 1,2,3,4 N: 4
Array: 1,2,3,4,5 N: 5
答案 3 :(得分:0)
如果你像这样在这里放置一个控制台日志,你可以更好地将其可视化。
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countup(n - 1);
countArray.push(n);
console.log(`countup(${n}) returns ${countArray}`);
return countArray;
}
}
console.log(countup(5));
发生的情况是,一旦您第一次调用 countup
,执行就会移动到那里。所以,用 5 调用它,你会看到第一个输出语句用 1 运行,因为它基本上又调用了几次。
countup(5)调用countup(4)调用countup(3)调用countup(2)调用countup(1)-- countup (1) 返回 1,返回给 2 的调用者返回 2, 1,返回到 3 的调用者返回 3, 2, 1 ... 依此类推回到 5。