尾递归和尾递归的优化

概念

首先有一个概念是尾调用,就是指某个函数的最后一步是调用另一个函数,如下

function f(x){
  return g(x);
}

而下面几种情况都不属于调用

1.
function f(x){
  let y = g(x);
  return y;
}

2.
function f(x){
  return g(x) + 1;
}

3.
function f(x){
  g(x);
  //相当于 return undefined
}

顾名思义,尾递归就是在函数尾部进行递归调用。
 

作用

尾递归本身只是一种coding方式,但加以利用可以对一些递归操作进行优化,避免栈溢出。
比如一些求阶乘的例子:

不使用尾递归

// 无尾递归优化
function f(n) {
   	if (n === 1) 
   		return 1
   
   	return n * f(n - 1)
}

这并不是一个尾递归,因为函数结尾不仅是递归调用函数,而是多了一个n的运算,意味着计算完f(n-1),还需要回来乘上n。导致这一上下文需要被保存,计算n的阶乘,就需要保存n个上下文记录。
 

使用尾递归

// 第一次调用f时,total设为1
function f(n, total = 1) { 
    if (n === 1) 
    	return total
    
    return f(n - 1, n * total) // total 结果和 n 相乘作为参数放入到函数中
}

f 尾部进行递归调用,且将当前结果作为参数传入递归中,那么当前的栈帧就不用保存了,编译时实际上是按照循环的方式执行,相当于如下代码:

function f(n){
	let total = 1;
	for(let i=n;i>0;i--){
		total = total * i;
	}
	return total
}

目前一些主流浏览器并不支持尾递归的优化,因此在coding的使用多用循环代替递归是个不错的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值