从this SO-question中的选定答案中,这个非常巧妙的函数会创建一个范围从1到i的数组:
function range1(i){return i?range1(i-1).concat(i):[]}
它完美无缺。叫我傻,但我无法理解 它是如何运作的。假设我们有range1(5)
。现在进入函数,我们有i
,因此它返回参数i-1
(4)并将i
(5)连接到它。但在这里我被困住了:range1
如何知道它与数组有什么关系?我会说在第一次运行后返回值(只要我们有i
,所以i!==0
)就是一个数字。并且Number没有concat
方法。有人可以解释一下吗?我错过了什么?
答案 0 :(得分:11)
我已经扩展了这段代码,因为我发现这种方式更容易理解。
function range1(i){
if (i != 0) {
return range1(i - 1).concat(i);
} else {
return [];
}
此功能背后的逻辑是,如果您需要3
元素列表(range(3)
),则可以获取2
元素列表(range1(i - 1)
)并添加3
到它的末尾.concat(i)
。除此之外,您只需处理range1(0)
为空数组[]
的特殊情况,您就完成了。
想象一下对range1(2)
的调用。自i != 0
以来,我们得到了
range(2) = range(1).concat(2)
range(1)
返回range(0).concat(1)
,告诉我们
range(2) = range(0).concat(1).concat(2)
嗯,range(0)
是什么?从i == 0
开始,我们得到了我们需要的空数组([]
)!
range(2) = [].concat(1).concat(2) -> [1, 2]
答案 1 :(得分:9)
现在进入这个功能,我们有, 所以它用参数返回自己 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]
{1}},等等。当我们返回range1(5)
时
它会返回[1,2,3,4].concat(5)
[1,2,3,4,5]
。
注意:此函数适用于创建小型数组,但如果需要大型数组,则创建数组并使用常规循环填充它会快得多。
答案 2 :(得分:2)
递归的基本情况是[]
,因此递归的尾部将返回一个数组,其他步骤将连接到[]
(以及之前的步骤)。
答案 3 :(得分:2)
我们取范围1(4):
range1(4) => range1(3).concat(4)
range1(3) => range1(2).concat(3)
range1(2) => range1(1).concat(2)
range1(1) => range1(0).concat(1)
range1(0) => []
现在取第一行并将range1(3)替换为下一行的等效值。你明白了:
range1(4) => range1(2).concat(3).concat(4)
继续替换range1引用,直到没有任何剩余。最终结果:
range1(4) => [].concat(1).concat(2).concat(3).concat(4)
答案 4 :(得分:0)
range1
函数始终返回一个数组。
它是一个空数组(对于i == 0)或连接数组。
答案 5 :(得分:0)
在基本情况下range1
返回一个定义concat
的空数组。然后,当它展开时,范围中的数字被添加到数组中。
答案 6 :(得分:0)
直到我变成0除了使用带有rediced值的caling函数之外没什么好处,但是当它用0调用时它返回[] - 一个空数组,在前一个调用中使用了concat方法......它看起来像range(0)。 concat(1)=> [] .concat(1)所以[1]返回上一个调用:[1] .concat(2)等等开始