这个递归函数如何创建范围工作?

Koo*_*Inc 6 javascript arrays recursion

这个SO问题中的选定答案,这个非常巧妙的函数创建一个范围从1到i的数组:

function range1(i){return i?range1(i-1).concat(i):[]}
Run Code Online (Sandbox Code Playgroud)

它完美无缺.叫我傻,但我无法理解它是如何工作的.让我们说我们有range1(5).现在进入函数,我们有i,所以它返回自己的参数i-1(4)和concats i(5).但在这里我被困住了:怎么range1 知道它与数组有关?我会说在第一次运行后返回值(只要我们有i,所以i!==0)将是一个数字.而Number没有concat方法.有人可以解释一下吗?我错过了什么?

小智 11

我已经扩展了这段代码,因为我发现这种方式更容易理解.

function range1(i){
  if (i != 0) {
     return range1(i - 1).concat(i);
  } else {
     return [];
}
Run Code Online (Sandbox Code Playgroud)

这个函数背后的逻辑是,如果你想要3元素列表(range(3)),你可以获取2元素列表(range1(i - 1))并添加3到它的末尾.concat(i).除此之外,你只需要处理range1(0)空数组的特殊情况,[]你就完成了.

想象一下打电话给range1(2).因为i != 0,我们得到

range(2) = range(1).concat(2)
Run Code Online (Sandbox Code Playgroud)

range(1)回来range(0).concat(1),给我们

range(2) = range(0).concat(1).concat(2)
Run Code Online (Sandbox Code Playgroud)

那是range(0)什么?因为i == 0,我们得到了[]我们需要的空数组()!

range(2) = [].concat(1).concat(2) -> [1, 2]
Run Code Online (Sandbox Code Playgroud)


Guf*_*ffa 8

现在进入函数,我们有i,所以它返回参数i-1(4)和concats i(5).

不,它不会自行返回.它的作用是调用自身,即递归,然后它返回该调用的结果,最后一个元素连接起来.

所以,range1(5)会打电话range1(4),打电话range1(3),等等.当它达到零时,它将停止进行调用并返回一个空数组.

range1(0)回报[],所以range1(1)回报[].concat(1)[1],则range1(2)返回[1].concat(2)[1,2],依此类推.当我们回到range1(5) 它返回[1,2,3,4].concat(5)[1,2,3,4,5].

注意:此函数适用于创建小型数组,但如果需要大型数组,则只需创建数组并使用常规循环填充它就会快得多.