首先我们先要知道一个概念:什么是尾调用
一句话讲解就是:某个函数的最后一步调用另外一个函数,记住这句话,我们下面要用
让我们来看几个例子
function f(x){
let y = g(x)
return y;
}
这就不是尾调用,因为调用g函数之后还进行了赋值操作。
function f(x){
return g(x) + 1
}
这也不是尾调用,因为调用g函数之后进行了运算
function f(x){
g(x)
}
这看似是尾调用,但其实不是,我们知道函数有默认返回值
return undefined
真正的尾调用如下
function f(x){
return g(x)
}
相信大家看完这些,一定对尾调用有了大概的了解。
让我们再看个例子,更好地明白为什么要使用尾调用
function C(){
console.log('c');
}
function B(){
C();
}
function A(){
B();
}
A();
此时执行栈如下
让我们改造一下以上代码
function C(){
console.log('c');
}
function B(){
return C();
}
function A(){
return B();
}
A();
相信大家看出来了,这使用了尾调用方法
此时的执行栈如下
此时相信大家已经明白尾调用是可以如何的节省空间,提高效率了。
下来再让我看一下尾递归
函数调用自身叫做递归
尾调用自身叫做尾递归
让我们看一下简单的斐波那契数列
function fb(n){
if(n <= 1){
return 1;
}
return fb(n-1)+ fb(n-2)
}
此时我们如果计算fb(5)
执行栈就会不断的累积,直至栈溢出
可以试着执行一下fb(100)
下面我们开始进行优化,一般我们进行尾递归优化时,确保最后一步只调用自身,就是把所有用到内部变量的改写成函数的参数。
function fb(n,total = 1){
if(n === 1){
return total;
}
return fb(n-1,n*total)
}
在es6 中,我们可以使用参数默认值,这是最简单的方法。
否则只能使用另外的函数分隔,或者写多个参数。
(比较麻烦,所以就不在这里介绍啦)
现在可以再运行一下fb(100)试试。
能看到结果了吗
参考<<ES6标准入门>> 阮一峰
大家想看什么可以发给我哦,能力范围之内,都会不定时更新…