递归可替代循环,核心是函数调用自身,需满足终止条件和向终止条件推进;适用于遍历数组、累加计算、嵌套结构处理,但需防栈溢出,简单场景优先用循环。

递归可以替代 for、while 等循环,核心是把“重复执行”转化为“函数调用自身”,但需满足两个关键条件:有明确的终止条件,且每次递归调用必须向终止条件靠近,否则会栈溢出。
用递归遍历数组(代替 for 循环)
传统 for 循环逐个访问元素,递归则把“处理第 i 个元素 + 处理剩余部分”拆解为子问题。
例如,打印数组所有元素:
function printArray(arr, index = 0) {
if (index >= arr.length) return; // 终止条件
console.log(arr[index]);
printArray(arr, index + 1); // 向终止条件推进
}对比 for 循环,这里没有显式的循环变量和边界判断语句,逻辑被封装在参数和递归调用中。
立即学习“Java免费学习笔记(深入)”;
用递归实现累加或累积计算(代替 while 或 reduce)
求 1 到 n 的和,循环写法依赖状态变量;递归则聚焦“n 的和 = n + (n−1) 的和”这一关系。
示例:
function sumTo(n) {
if (n <= 0) return 0; // 终止条件(含边界)
return n + sumTo(n - 1);
}注意:该写法是“线性递归”,调用栈深度为 n;若 n 过大(如 >10000),可能触发 RangeError。生产环境建议配合尾递归优化(需引擎支持)或改用迭代。
用递归处理嵌套结构(天然优势场景)
循环难以优雅处理树、DOM、JSON 等嵌套数据;递归则与结构同构,代码更直观。
例如,深度优先遍历一棵树(每个节点有 children 数组):
function traverse(node) {
if (!node) return;
console.log(node.value);
if (Array.isArray(node.children)) {
node.children.forEach(child => traverse(child)); // 对每个子节点递归
}
}这种“访问当前 → 递归处理子结构”的模式,比手动维护栈或队列的循环实现更简洁、不易出错。
注意事项与实用建议
- 始终先写终止条件,再写递归调用,避免无限递归
- 递归参数应体现“规模缩小”,比如索引+1、数组切片、n-1、子节点等
- JavaScript 默认不优化尾递归(ES2015 规范虽定义,但主流引擎未启用),不要依赖它规避栈溢出
- 简单线性任务(如遍历平数组)优先用循环;递归更适合分治、回溯、嵌套结构等场景


















