JavaScript 递归函数怎么写
你有没有遇到过这种情况:要算从1加到100的总和,除了用简单的等差数列公式,还能怎么写代码?要是换成分解成“把大问题拆成一模一样的小问题”,你会发现这正是JavaScript递归函数的拿手好戏。
先搞懂:递归就是“自己调用自己”
别被“递归”这俩字吓住,它本质就是函数内部,又调用了一遍自己。但递归要能跑起来,关键得有两个部分:一是“重复做的小事”,二是“停下来的理由”。举个生活化的例子,你要把100块零花钱分给10个小朋友,每次只分10块,直到剩0块就停——这里“每次分10块”是重复动作,“剩0块”就是停下来的规则,缺了任何一个都不行。

很多人一开始会踩坑:只写了“自己调用自己”,没写停止规则,结果代码一直跑,最后弹出“栈溢出”的错误,就像你一直分零花钱,永远不说停,最后自己都记不清分给谁了。
写递归的第一步:先定“停止规则”
写递归的顺序很重要,得先想清楚“什么时候停”,再写“怎么调用自己”。就像你要数完书架上所有的书,不会从第一本开始数到最后,而是先确定“数到空书架就停”。
举个简单的小例子:用递归写一个数到5的函数。先定停止规则:如果数字等于0,就返回“数完啦”;再写调用自己的部分:每次数当前数字,再数下一个数字。代码大概是这样:
`javascript
function count(num) {
// 停止规则:num是0就停
if (num === 0) {
console.log("数完啦");
return;
}
// 重复动作:先打印当前数字,再调用自己数前一个数
console.log(num);
count(num - 1);
}
count(5);
`
运行后会依次打印5、4、3、2、1,最后是“数完啦”。这里的停止规则就是num === 0,要是把它删掉,代码会一直减到负数,直到浏览器崩溃,这就是没停止规则的后果。
第二步:写“可拆分的小问题”
再拿大家更熟悉的求和举例,比如算1到n的总和。大问题是“算1到10的和”,可以拆成“算1到9的和,再加10”;而“1到9的和”又能拆成“1到8的和,再加9”,以此类推,直到拆成“1到1的和,再加2”——而1到1的和就是1,这就是最小的可拆分问题,也是停止规则的一部分。
把这个思路写成JavaScript递归函数:
`javascript
function sum(n) {
// 停止规则:n是1的时候,和就是1
if (n === 1) return 1;
// 拆分逻辑:n的和 = (n-1)的和 + n
return sum(n - 1) + n;
}
console.log(sum(10)); // 输出55,和等差数列公式算的一样
`
你看,不用写循环,靠函数自己调用自己,就把10次加法的事搞定了。要是换成循环,代码要多写两行判断,递归的好处就是把大问题拆成一模一样的小步骤,逻辑更清楚。
常见的小误区要避开
最后说两个新手容易踩的坑:一是停止规则写反,比如把n === 1写成n > 1,那函数会一直调用自己,直到n变成负数,直接崩溃;二是拆分逻辑错了,比如求和写成sum(n) = sum(n) + n,没拆成更小的问题,相当于自己永远调用自己,也会出问题。
其实递归不止是代码里的技巧,平时整理衣柜的时候,把一堆衣服分成“上衣”“裤子”,再把上衣分成“短袖”“长袖”,也是递归的思路——把大任务拆成重复的小任务,直到不用再拆,就完成了。只要记住“先停、再拆、别写错”,写JavaScript递归函数就没那么难了。