递归如何在倒计时函数中工作
How does recursion work in a Countdown function
我正在学习一些 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.
- js遇到的下一个操作是
countArray.push(n)
,所以它会将4压入一个数组
- 然后遇到
return countArray
,也就是4.
- 函数继续执行 3,2,1 直到基本条件达到
n==0
,在这种情况下
函数结束时返回一个空数组。
我知道这不是它的工作原理,我只是在“描述”我的菜鸟思维如何看待这个递归函数。
我看了习题的解法和别人的解释,但是我无法理解为什么函数没有像我描述的那样工作,以及为什么在达到n==0
之后,它开始填充一个数组从 1 数到 5。
我想了解一下。
这里是每个函数调用中数组的样子,如果有帮助的话:
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
如果你把控制台日志像这样放在这里,你可以更好地形象化它。
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) returns 1,返回到 2 的调用者 which returns 2, 1,返回到 3 的调用者 returns 3, 2, 1...等等最多 5 个。
您可以只添加一些日志记录来可视化正在发生的事情:
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));
意识到 countup
的每次执行都会有自己的 n
和 countArray
变量。
想象一下可能会有所帮助。每个执行上下文被可视化为一个“盒子”。当函数调用 returns.
时,外框中的变量仍然存在
最外面的框是初始调用创建的执行上下文: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]
我正在学习一些 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. - js遇到的下一个操作是
countArray.push(n)
,所以它会将4压入一个数组 - 然后遇到
return countArray
,也就是4. - 函数继续执行 3,2,1 直到基本条件达到
n==0
,在这种情况下 函数结束时返回一个空数组。
我知道这不是它的工作原理,我只是在“描述”我的菜鸟思维如何看待这个递归函数。
我看了习题的解法和别人的解释,但是我无法理解为什么函数没有像我描述的那样工作,以及为什么在达到n==0
之后,它开始填充一个数组从 1 数到 5。
我想了解一下。
这里是每个函数调用中数组的样子,如果有帮助的话:
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
如果你把控制台日志像这样放在这里,你可以更好地形象化它。
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) returns 1,返回到 2 的调用者 which returns 2, 1,返回到 3 的调用者 returns 3, 2, 1...等等最多 5 个。
您可以只添加一些日志记录来可视化正在发生的事情:
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));
意识到 countup
的每次执行都会有自己的 n
和 countArray
变量。
想象一下可能会有所帮助。每个执行上下文被可视化为一个“盒子”。当函数调用 returns.
时,外框中的变量仍然存在最外面的框是初始调用创建的执行上下文: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]