function foo( n ){
if(n <= 1){
return 1;
}
return n * foo( n - 1 );
}
foo(5); // 120
现在上下文栈中已经有了两个执行上下文了
现在上下文栈中已经有了三个执行上下文了
此刻上下文栈中,已经有了6个上下文了(包含了全局上下文)
RangeError: Maximum call stack size exceeded
function outer() {
return inner();
}
outer();
分析一下,这里的上下文栈是怎么变化的
第一个栈帧是全局上下文
把上下文栈中的一个上下文称作一个栈帧
这个时候,栈中只有一个栈帧了--全局上下文
这个时候,栈中有两个栈帧了
栈中又只剩一个栈帧了--全局上下文
综上,我们可以看出:如果没有优化,没多调用一次嵌套函数,就会多增加一个栈帧;有了优化之后,无论调用多少次嵌套,栈中只会有两个栈帧。这就是ES6尾调用优化的关键😄
// 无优化: 尾调用没有返回
function outer(){
inner();
}
// 无优化: 尾调用没有直接返回
function outer(){
let innerResult = inner();
return innerResult;
}
//无优化: 尾调用返回值后,必须要转型为字符串
function outer(){
return inner().toString();
}
// 无优化: 尾调用是一个闭包
function outer(){
let foo = 'bar';
function inner(){ return foo; }
return inner();
}
其实我觉得上面的倒数第二个,它是完全可以尾调用优化的。因为这个计算是不需要外部函数的上下文里面内容支持的。可能是这样的计算必须要在外部函数的上下文中完成吧,咱也不懂。记一下吧。
有哪位同仁能够帮我解答一下我这个问题吗😁
function fib( n ){
if( n < 2){
return n;
}
return fib(n - 1) + fib(n - 2)
}
这是一个非常简单的斐波那契数列的函数,可以看到它不符合尾递归的条件。因为返回值的调用函数参与了额外计算
function fib( n ){
return fibImpl(0, 1, n);
}
function fibImpl(a, b, n){
if(n === 0){
return a;
}
return fibImpl(b, a+b, n-1);
}
看,这样是不是就符合尾递归调用函数了
简单讲解一下上面的代码
斐波那契数规律,就是从第三位开始,每一位的数字都是前两位数字的和
function foo( n ){
if(n <= 1){
return 1;
}
return n * foo( n - 1 );
}
foo(5); // 120
这个是上面计算阶乘的代码,我们可以用同样的思路,来对其做尾递归函数优化
function foo( n ){
return inner(n, n - 1)
}
function inner(sum, n){
if(n <= 1){
return sum;
}
return inner(sum * n , n -1);
}
foo(5);
是不是超简单😁
可以在计算斐波那契数列的时候,比较尾递归和非尾递归的时间。相信你会和我一样,会不由自主的感叹
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。