递归和尾递归

202 阅读2分钟

由于递归是调用函数自身,而函数调用需要消耗时间和空间:每次调用都要在内存栈中分配空间以存储参数、临时变量、返回地址等,往栈中压入和弹出数据都需要消耗时间。这势必导致执行效率大打折扣。

尾递归是一种可以避免不断的将函数压栈导致堆栈溢出的递归解决方案。他的技术原理是:在函数中return一个函数后,当前函数在栈内的调用记录会被删除,当前函数的执行上下文会从调用栈弹出。

一般的递归在函数体中断点能够看到在栈内会创建大量的执行上下文并且不销毁(这就是造成栈溢出的原因);而尾递归是在栈内增加函数执行上下文,然后在该函数返回函数时,销毁当前函数执行上下文,创建返回的函数的执行上下文。所以尾递归中只有一个活跃的执行上下文。

但是尾递归也有自己的一些缺陷。如尾递归是一个隐式行为,如果代码存在死循环尾递归调用,爆栈后难以被开发者察觉;堆栈信息会丢失,造成调试困难。还有目前各大浏览器厂商对尾递归的支持和兼容性不太好。所以在尾递归目前还不被各大浏览器支持的情况下,可以对递归的一些重复内容做优化。

  • 我们在拿到一个功能的时候,首先会分析这个功能是不是能够用递归来实现。写出好的递归需要从这两步来做:(1)编写出递归公式;(2)找到终止条件。
  • 如果递归的层级太深或者数据量过大时,可能会引起栈溢出。而解决栈溢出的方法一般有尾递归,循环方式,事件循环方式
  • 尾递归的原理是在一个递归函数中返回一个函数,当前函数在栈内的调用记录会被删除,这时会把原函数中的执行上下文从执行栈中弹出。
  • 还有一个就是可以通过Map这种数据结构对相同值的计算进行保存,减少重复计算

参考:lequ7.com/js-ji-chu-x…

参考:(三)不可不说的JS重点知识~递归和尾递归(测试小姐姐专题) - 掘金 (juejin.cn)