JavaScript递归原理与经典案例实战解析
本文深入解析JavaScript递归机制,阐述基本情况与递推关系两大核心属性。通过数字求和、数组求和、扁平数据转树形结构、汉诺塔游戏逻辑及斐波那契数列五个经典案例,详细演示递归调用栈的执行顺序与代码实现,帮助开发者掌握递归技巧并避免死循环。
什么是递归,它是如何工作的?
我们先来看一下递归(recursion)的定义:
递归是一种解决问题的有效方法,在递归过程中,函数将自身作为子例程调用。
简单来说,程序调用自身的编程技巧称为递归。其核心思想是将一个大型复杂问题层层转化为规模更小的原问题,拆解为子问题后继续递归调用,直到子问题无需进一步递归即可解决为止。
使用递归时必须避免死循环。为确保递归正确运行,递归程序应包含两个关键属性:
- 基本情况(bottom cases),用于保证程序调用及时返回,不再继续递归,从而确保程序可终止。
- 递推关系(recurrence relation),可将所有其他情况拆分到基本案例。
函数中自己调用自己就是递归,切记要有终止条件,不然进入死循环
一、求和
(1)数字求和
function sum(n){
if(n===1){
return n=1
}
return n+sum(n-1)
}
console.log(sum(5));
执行顺序
5+sum(n-1) 5+4+sum(n-1) 5+4+3+sum(n-1) 5+4+3+2sum(n-1) 5+4+3+2+1
(2)数组求和
function sum(arr) {
var len = arr.length
if (len == 0) {
return 0
} else if (len == 1) {
return arr[0]
} else {
return arr[0] + sum(arr.slice(1))
}
}
let arr = [ 1, 2, 3, 4, 5 ]
console.log(sum(arr))
执行顺序
1+sum(2,3,4,5) 1+2+sum(3,4,5) 1+2+3(4,5) 1+2+3+4+sum(5) 1+2+3+4+5 1+2+3+9 1+2+12 1+14 15
二、数据转树
let data = [{
id: "01",
pid: "",
"name": "老王"
},
{
id: "02",
pid: "01",
"name": "小张"
}
]
function fn(data, rootId = '') {
const children = [] //定义一个空数组
data.forEach(item => {
if (item.pid === rootId) { //如果每一项的pid=rootId就添加到数组里
children.push(item)
item.children = fn(data, item.id)
}
});
return children
}
使用递归转树 要知道根的pid是什么值才能进行下一步操作,作为起点。
执行顺序

三、汉诺塔
规则 下面三个柱子分别设为 a 、b、 c、 目标把a中的所有盘子分别从大到小依次放到c柱子中,每次只能移动一个盘子

实现思路:
- 将n-1个盘子从a挪到b
- 将n盘子从a挪到c
- 将n-1个盘子从b挪到c
function fn(num, start, middle, end) {
if(num>0){
fn(num-1,start,end,middle)
console.log(start+'====>'+end);
fn(num-1,middle,start,end)
}
}
fn(2,'a','b','c')
把 num作为盘子的数量 start 作为a盘子 middle作为b盘子 end作为c盘子
例如 2个盘子的执行顺序
1.第一行 把2带进去 num>0 执行第一个函数fn(2-1,start,end,middle) 又去执行了fn(1-1,start,end,middle) 发现num不大于0不仅如此if条件,回过来看 fn(2-1,start,end,middle) ,输出 console.log(a===>b)
2.第二行console.log(start+'====>'+end); 直接输出 a===>c
3.第三行 fn(2-1,middle,start,end) 执行 console.log(b===>c) 下次再去执行 fn(1-1,middle,start,end) 进入不了循环执行完毕
执行顺序有点抽象,实在不理解就按照最简单的思路去做 fn(num, start, middle, end) ,平常我们玩游戏怎么玩就去怎么做,初始图
fn(num-1,start,middle,end) 把 第二个的参数位置作为要移动的盘子 把第四个的参数位置作为移动目标 每次看图把这个公式带进去

第一步 fn(num-1,start,end,middle) 例如两个盘子 肯定是先把a-1放到b上

第二步 把盘子a放c上直接输出 console.log('a===>c')

第三步 把盘子b放c上 fn(num-1,middle,start,end,)

四、斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、
function Fibonacci(n) {
return n <= 1?1:Fibonacci(n - 1) + Fibonacci(n - 2)
}
除了前两个 每次都是前一个数和前两个数的和相加等于第三个数
例如数字5举例 前一项是3 前两项是2 3+2=5
总结
到此这篇关于JavaScript递归经典案例题详析的文章就介绍到这了,更多相关JavaScript递归案例内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
D3.js 与 ECharts 选型对比:灵活性 vs 开发效率
2026-11-05 09:45:01
为什么JS中typeof []返回object:数组类型检测误区解析
2026-11-04 19:50:47
