Javascript递归为什么以下代码与.unshift而不是.push一起工作?

问题描述

我的大脑认为我应该使用.push()而不是.unshift(),但是freeCodeCamp和控制台表明这是正确的方法。我只是不明白如何使用.unshift()将数字从10变为20,而使用.push()将数字从20变为10;

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

我在做什么错了?

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将一个元素插入数组的开头。

由于您是从startNumendNum进行迭代,因此请考虑倒数第二个递归调用:

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,arr);
  }
  return arr;
}

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

,

一种思考的方式是想象递归调用已经正常工作。因此rangeOfNumbers(11,20)将产生[11,12,13,14,15,16,17,18,20]。因此const arr = rangeOfNumbers(startNum + 1,endNum)意味着arr[11,20]。现在您有了startNumarr,需要将它们结合起来。 pushstartNum添加到末尾。 unshift正确地将其添加到开头。

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

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

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