什么是递归_如何在javascript中编写递归函数【教程】

12次阅读

递归是解决自相似结构问题的自然表达方式;写错主因是缺终止条件或参数错误,base case作为“刹车”须明确,如阶乘中factorial(0)返回1、树遍历遇NULL返回、字符串反转以空串为base case。

什么是递归_如何在javascript中编写递归函数【教程】

递归不是“必须用循环替代的高级写法”,而是**解决具有自相似结构问题的自然表达方式**;在 javaScript 中写错递归,八成是因为忘了终止条件或误传参数。

递归函数必须有明确的 base case

没有终止条件的递归会一直调用自身,直到溢出报错 RangeError: Maximum call stack size exceeded。base case 是递归的“刹车”,它不调用自身,直接返回结果。

  • 比如计算阶乘:factorial(0)factorial(1) 应直接返回 1,不能继续调 factorial(-1)
  • 遍历树结构时,遇到 null 或叶子节点(无子节点)就要 return,不能对 node.children 做无条件递归
  • 字符串处理中,空字符串 "" 常是天然的 base case,比如反转字符串:if (str.Length

每次递归调用必须向 base case 靠拢

光有 base case 不够,还要确保每次调用都在缩小问题规模。否则即使写了 if (n === 0) return 1,若调用写成 factorial(n) 而非 factorial(n - 1),照样死循环。

  • 数组操作:递归处理 arr.slice(1) 或传入索引 i + 1,而不是反复传整个原数组
  • 数字计算:用 n - 1Math.floor(n / 2) 等可收敛的变换,避免 n - 0.5(浮点误差可能导致永远达不到 0)
  • 对象/树遍历:只对已知存在的子节点递归,比如 node.left && traverse(node.left),而非盲目访问 node.left 后再判空

javascript 中注意调用与尾递归的实际限制

ES6 规范支持尾递归优化(TCO),但**目前仅 Safari 默认启用,Chrome 和 Firefox 已移除 TCO 支持**。这意味着即使写成尾递归形式,也无法避免栈增长。

立即学习Java免费学习笔记(深入)”;

  • 尾递归写法(看似优化):function sum(n, acc = 0) { return n === 0 ? acc : sum(n - 1, acc + n); } —— 在 Chrome 中仍会栈溢出
  • 深度超过 ~10000 层的递归,在多数引擎中都会触发 RangeError
  • 真实项目中,若预估深度较大(如解析深层嵌套 JSON、DOM 树遍历),优先考虑显式栈(Array.push()/.pop())或迭代重写

递归最易被忽略的不是语法,而是“问题是否真具备递归结构”——强行把线性任务(如累加数组)写成递归,除了增加栈开销和调试难度,几乎没有收益。

text=ZqhQzanResources