简体   繁体   English

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

[英]Beginner's question about a recursion example in JS

I'm a beginner going through a JS tutorial and got stuck trying to understand the order of statement execution in this example of a recursive function:我是一名初学者,正在阅读 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 ]

I assumed, that each time const countArray = countup(n - 1);我假设,每次const countArray = countup(n - 1); line is reached, it throws the execution back to line 1 with decremented n .到达第 1 行,它将执行返回到第 1 行并递减n That would explain the output array starting at 1 and going upwards, while n is going down.这将解释输出数组从 1 开始向上移动,而n向下移动。 But in that case, shouldn't the function just return empty array [], since n would drop below 1, satisfying the first if and terminating before anything having been pushed into countArray ( else )?但在这种情况下,函数不应该只返回空数组 [],因为n会低于 1,满足第一个if并在任何内容被推入 countArray ( else ) 之前终止? **Tried googling about the use of breakpoints to see the actual flow, but only saw their uses in non-loops **尝试谷歌搜索断点的使用来查看实际流程,但只看到它们在非循环中的使用

Let's simply assume that every function call with all its information will be stored in a stack.让我们简单地假设每个函数调用及其所有信息都将存储在堆栈中。 Note, stacks are LIFO(Last In First Out).请注意,堆栈是 LIFO(后进先出)。

So in your code, countup(5) will be called and stored in stack[0] .因此,在您的代码中, countup(5)将被调用并存储在stack[0]

Then inside the else condition it is again called as countup(4) .然后在 else 条件中,它再次被称为countup(4) This will pause countup(5) from being executed and countup(4) will be stored in the stack[1] .这将暂停countup(5)执行,并且countup(4)将存储在stack[1]

Just like this until n<1 countup will be called with a lower value and stored in stack.就像这样,直到n<1 countup 将被调用一个较低的值并存储在堆栈中。

At the end of all calls, stack will be like,在所有调用结束时,堆栈将像,

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

Now popping from stack will start.现在将开始从堆栈中弹出。 As stack is LIFO so element at top of the stack will be popped.由于堆栈是 LIFO,因此堆栈顶部的元素将被弹出。 Popped means you're deleting that element from your stack.弹出意味着您要从堆栈中删除该元素。

countup(1) will be popped first and finish its execution. countup(1)将首先弹出并完成其执行。 That is countArray.push(1) .那是countArray.push(1)

Then countup(2) will be at the top of stack.然后countup(2)将位于堆栈顶部。 So, countup(2) is popped and finish its execution countArray.push(2) .因此, countup(2)被弹出并完成它的执行countArray.push(2)

Just like this, countup(3) is popped and finish its execution countArray.push(3) .就像这样, countup(3)被弹出并完成它的执行countArray.push(3) countup(4) is popped and finish its execution countArray.push(4). countup(4)被弹出并完成它的执行 countArray.push(4)。 countup(5) is popped and finish its execution countArray.push(5) . countup(5)被弹出并完成它的执行countArray.push(5)

At the end the entire array is returned.最后返回整个数组。

*I've described it in simple terms. *我已经用简单的术语描述了它。 The real execution behind the hood has a lot more things going and has a lot other terms to know about.引擎盖背后的真正执行还有很多事情要做,还有很多其他的术语需要了解。 You can check this article that describes how recursion works in JS你可以查看这篇文章,它描述了递归在 JS 中是如何工作的

I don't know if you're familiar with the "spread" syntax, but it might be easier to see what's going on if the body of the else clause were written as simply:我不知道您是否熟悉“spread”语法,但如果else子句的主体写成这样简单,可能更容易看出发生了什么:

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

That just means it's the array you get by taking countUp(n - 1) and adding the element n at the end.这只是意味着它是您通过采用countUp(n - 1)并在最后添加元素n获得的数组。 The code you show does the same, just in a slightly different way.您显示的代码执行相同的操作,只是方式略有不同。 Hopefully it's obvious from this description why the function does what it does - but if it still isn't, note that:希望从这个描述中可以明显看出为什么该函数会执行它所做的事情 - 但如果它仍然不是,请注意:

  • countUp(0) is empty countUp(0)为空
  • countUp(1) therefore consists of an empty array with an additional 1 on the end - so the singleton array [1]因此countUp(1)由一个空数组组成,末尾有一个额外的1 - 所以单例数组[1]
  • countUp(2) is the above with a 2 on the end: [1, 2] countUp(2)是上面最后一个2[1, 2]

and so on.等等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM