- 递归 : 函数调用自己本身
计算n的阶乘
function add(n){
if(n===1){
return n;
}
return n*function add(n-1)
}
斐波那契数列 1 1 2 3 5 8 13...
function arr(n){
if(n===1){
return n;
}
else{
return function arr(n-1)+function arr(n-2)
}
}
如上实例,但是递归有一个很大的问题,就是在不断地调用自身函数时,每一次调用都会存新的数据变量等,如果有成百上千次调用,则会占用特别特别特别多内存,就有可能会导致栈溢出,就是栈存不下了!!!
但是 在es6中,有一个明确的概念就是尾调用!!!尾调用!!!尾调用!!!(重要的事情说三遍)可以完美的解决这个问题
尾调用: 就是在函数最后一次执行时,调用一个函数。
等等,是不是看起来感觉和递归没啥区别啊,不都是最后调用一个函数嘛,只不过递归是调用自己,实则不然嘻嘻。
尾调用要求最后一步仅仅只调用这个函数,别的什么都不能干 不然就不叫尾调用!
function fn(){
return g()
} //=>这叫尾调用
function fn(){
return g()+1
}//=>这就不是尾调用了
通过上面两个例子可以看出,最后一步除了调用这个函数意外什么也不允许做,否则就不是尾调用,为什么是这样呢,因为在这种情况下,最后只调用一个函数,则整个大函数中,就不用保存外层函数的调用记录,也就是说外层函数的变量等都不需要保存了,内存就被释放了。
在递归中,使用尾调用方法解决栈溢出问题。
在普通的递归中,n的阶乘因为要调用n次函数,空间复杂度为O(n);而在尾递归中:
function add(n,all){
if(n===1){
return all;
}
return add(n-1,n*all)
}
add(3,1)
//n===3,all===1,return add(2,3);
//n===2,all===3,return add(1,6);
//n===1,all===6,return 6
斐波那契数列 尾递归实现
function fecth(n,x=1,y=1){
if(n<=1){
return n;
}
return fecth(n-1,y,x+y)
}
console.log(fecth(100))//=>9.332621544394415e+155
原始递归
function arr(n){
if(n===1){
return n;
}
else{
return function arr(n-1)+function arr(n-2)
}
}
console.log(arr(100))//=>Uncaught RangeError: Maximum call stack size exceeded