尾调用

1.1>简单概括:就是在函数最后一步调用另一个函数(不一定出现在函数尾部)并且不能出现赋值,加减等操作。

下面都不是尾调用:

// 情况一
function f(x){
	let y=g(x);
	return y;
}
// 情况二
function f(x){
	return g(x)+1
}
// 情况三
function f(x){
	g(x);
}

1.2>尾调用优化

“尾调用优化”就是只保留内层函数的调用帧,只要直接用内层函数的调用帧取代外层函数的调用帧就可以了。

“尾调用优化”的意义大大节省内存,因为每次执行时,调用帧只有一项,不会发生栈溢出

注意:只有不用到外层的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则无法进行尾调用。

function f(){
	let m=1;
	let n=2;
	return g(m+n);
}
console.log(f());
//等同于
function f(){
	return g(3);
}
f();
//等同于
g(3);
function addOne(a){
	var one=1;
	function inner(b){
		return b+one;
	}
	return inner(a)
}
console.log(addOne(4))

1.3>尾递归:尾调用自身就是尾递归

递归非常消耗内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误,但对于尾递归说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误

下面这个阶乘函数,计算n阶乘最多需要保存n个调用记录,复杂度是O(n)

function factorial(n){
	if(n<=1){
		return 1;
	}else{
		return n*factorial(n-1)
	}
}
console.log(factorial(3));

改写成尾递归后只要保留一个调用记录,复杂度O(1)

function factorial(n,total){
	if(n<=1){
		return total;
	}else{
		return factorial(n-1,n*total)
	}
}
console.log(factorial(3,1));

例子:计算Fibonacci数列

非尾递归会出现堆栈溢出

var Fibonacci=n=>n<=1?1:Fibonacci(n-1)+ Fibonacci(n-2);
console.log(Fibonacci(5));

尾递归优化过的Fibonacci数列

var Fibonacci=(n,ac1=1,ac2=1)=>n<=1?ac2:Fibonacci(n-1,ac2,ac1+ac2);
console.log(Fibonacci(100));

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值