简体   繁体   English

Javascript 递归。 为什么以下代码适用于 .unshift() 而不是 .push()?

[英]Javascript recursions. Why the following code works with .unshift() instead of .push()?

My brain believes that I should use .push() instead of .unshift() but freeCodeCamp and my console tell that this is the right way of doing it.我的大脑认为我应该使用.push()而不是.unshift()但 freeCodeCamp 和我的控制台告诉我这是正确的做法。 I just don't understand how come my numbers go from 10 to 20 using .unshift() , and 20 to 10 using .push() ;我只是不明白为什么我的数字使用.unshift()从 10 到 20,而使用.push() 20 到 10 ;

The way I read the code: if startNum is bigger than endNum return an empty array.我阅读代码的方式:如果startNum大于endNum返回一个空数组。 Otherwise, create a variable called arr and assign to it the current startNum increased by 1 each time the code runs and return it into the array.否则,创建一个名为arr的变量,并将每次代码运行时增加 1 的当前startNum分配给它,并将其返回到数组中。

What am I doing wrong?我究竟做错了什么?

function rangeOfNumbers(startNum, endNum) {
  if (startNum > endNum) {
    return [];
  } else {
    const arr = rangeOfNumbers(startNum + 1, endNum);
    arr.unshift(startNum);
    return arr;
  }
}

console.log(rangeOfNumbers(10, 20));

The console: (11) [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]控制台: (11) [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

unshift inserts an element into the beginning of the array. unshift将一个元素插入到数组的开头。

Since you're iterating from the startNum to the endNum , consider the next to last recursive call:由于您是从startNum迭代到endNum ,请考虑下一个递归调用:

const arr = rangeOfNumbers(startNum + 1, endNum);
arr.unshift(startNum);
return arr;

where startNum is 19 and endNum is 20. The recursive call returns an array with one element: [20] .其中startNum是 19, endNum是 20。递归调用返回一个包含一个元素的数组: [20] Then you need to insert the 19 element in the proper position.然后你需要在适当的位置插入19元素。

To do this, you'll need to insert the 19 at the beginning, to get:为此,您需要在开头插入 19,以获得:

[19, 20]

So, insert 19 at the beginning with unshift .所以,用unshift在开头插入 19 。

If you used push instead, from the original [20] , you'd get:如果您改用push ,那么从原来的[20] ,您会得到:

[20, 19] // 19 added to end

and then进而

[20, 19, 18] // 18 added to end

and so on, which isn't in the right order.等等,顺序不对。

You could use push if you inserted elements before the recursive call.如果在递归调用之前插入元素则可以使用push

 function rangeOfNumbers(startNum, endNum, arr = []) { arr.push(startNum); if (startNum < endNum) { rangeOfNumbers(startNum + 1, endNum, arr); } return arr; } console.log(rangeOfNumbers(10, 20));

One way to think of it is to imagine that the recursive call already worked properly.一种思考方式是想象递归调用已经正常工作。 So rangeOfNumbers(11, 20) would yield [11, 12, 13, 14, 15, 16, 17, 18, 19, 20] .所以rangeOfNumbers(11, 20)会产生[11, 12, 13, 14, 15, 16, 17, 18, 19, 20] And so const arr = rangeOfNumbers(startNum + 1, endNum) means that arr is [11, 12, 13, 14, 15, 16, 17, 18, 19, 20] .所以const arr = rangeOfNumbers(startNum + 1, endNum)意味着arr[11, 12, 13, 14, 15, 16, 17, 18, 19, 20] Now you have startNum and arr and need to combine them.现在您有了startNumarr并且需要将它们组合起来。 push would add startNum to the end. push会将startNum添加到末尾。 unshift properly adds it to the beginning. unshift正确地将它添加到开头。

But while we're here, I'd like to suggest a more elegant way to express that same algorithm:但是当我们在这里时,我想建议一种更优雅的方式来表达相同的算法:

const rangeOfNumbers = (start, end) => 
  start > end 
    ? []
    : [start, ... rangeOfNumbers (start + 1, end)]

Instead of if-else statements we have a single conditional expression.我们有一个条件表达式,而不是if-else语句。 And we don't mutate a variable like arr in the process.我们不会在这个过程中改变像arr这样的变量。 I think it also more cleanly expresses the algorithm.我认为它也更清晰地表达了算法。 Of course tastes may vary, and, if you're just learning JS, this may involve syntax you haven't seen yet.当然口味可能会有所不同,而且,如果您只是在学习 JS,这可能涉及您尚未见过的语法。 But if you do understand it, you might agree with me about its elegance.但如果你确实理解它,你可能会同意我关于它的优雅。

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

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