繁体   English   中英

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

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

我的大脑认为我应该使用.push()而不是.unshift()但 freeCodeCamp 和我的控制台告诉我这是正确的做法。 我只是不明白为什么我的数字使用.unshift()从 10 到 20,而使用.push() 20 到 10 ;

我阅读代码的方式:如果startNum大于endNum返回一个空数组。 否则,创建一个名为arr的变量,并将每次代码运行时增加 1 的当前startNum分配给它,并将其返回到数组中。

我究竟做错了什么?

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));

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

unshift将一个元素插入到数组的开头。

由于您是从startNum迭代到endNum ,请考虑下一个递归调用:

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

其中startNum是 19, endNum是 20。递归调用返回一个包含一个元素的数组: [20] 然后你需要在适当的位置插入19元素。

为此,您需要在开头插入 19,以获得:

[19, 20]

所以,用unshift在开头插入 19 。

如果您改用push ,那么从原来的[20] ,您会得到:

[20, 19] // 19 added to end

进而

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

等等,顺序不对。

如果在递归调用之前插入元素则可以使用push

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

一种思考方式是想象递归调用已经正常工作。 所以rangeOfNumbers(11, 20)会产生[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] 现在您有了startNumarr并且需要将它们组合起来。 push会将startNum添加到末尾。 unshift正确地将它添加到开头。

但是当我们在这里时,我想建议一种更优雅的方式来表达相同的算法:

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

我们有一个条件表达式,而不是if-else语句。 我们不会在这个过程中改变像arr这样的变量。 我认为它也更清晰地表达了算法。 当然口味可能会有所不同,而且,如果您只是在学习 JS,这可能涉及您尚未见过的语法。 但如果你确实理解它,你可能会同意我关于它的优雅。

暂无
暂无

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

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