ES6 有两个新的东西,前端面试的时候偶尔会问道。之前也有在阮一峰的书上看过几次,但是没有统一归纳学习,今天归纳了一下。
尾调用 : 指函数最后一步调用另一个函数;
function f(x){
return g(x)
};
- 下面三个都不是属于尾调用
function a(x){
let y = b(x);
return y;
}
//调用后有赋值操作不属于尾调用
function c(x){
return d(x) + 1;
}
//调用后有运算操作
function a(x){
g(x);
}
//实际代码相当于
/***
function a(x){
g(x);
return undefined;
}
*/
- 尾调用不一定要出现在函数尾部,只要最后是一步操作即可
function f(x) {
if (x > 0) {
return m(x)
}
return n(x);
}
尾调用优化
- 为什么要用尾调用?尾调用优化代码的意义在哪里。
函数在调用的时候会在调用栈(call stack)中存有一条记录,每一条记录叫做一个调用帧(call frame),每调用一个函数,就向栈中push一条记录,函数执行结束后依次向外弹出,直到清空调用栈。
function a() {
console.log('如果有帮助请点个赞,大兄弟');
}
function b() {
a()
}
function c() {
b()
}
c();

造成这样的结果是因为每个函数在调用另一个函数的时候,没有return该调用,所以执行引擎会认为你还没有调用完毕,会保留调用帧。
而如果使用尾调用优化,调用帧就永远只有一条,这个时候就会节省很大一部分的内存空间,维护了代码运行的流畅性。
function a() {
console.log('如果有帮助请点个赞,大兄弟');
}
function b() {
return a()
}
function c() {
return b()
}
c();

以上代码就叫做尾调用优化,这个时候调用帧就永远只有一条,节省了部分内存。
尾递归
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
function test(){
return test(); //尾递归
}
- 计算一个数的阶乘,使用尾递归调用的优化
function multiplication(n) {
if (n === 1) return 1;
return n * multiplication(n - 1)
}
multiplication(4)//24
//尾递归
function multiplication1(n,init){
if(n === 1)return init;
return multiplication1(n -1 ,n*init)
}
multiplication(4,1)//24
//优化
function multiplication2(n,init=1){
if(n === 1)return init;
return multiplication2(n -1 ,n*init)
}
multiplication2(4);//24
- Fibonacci 数列使用尾递归优化
Fibonacci 数列:指的是这样一个数列:/1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*);
//递归形式Fibonacci 数列()
function Fibonacci (n) {
if ( n <= 1 ) {return 1};
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
Fibonacci(10) // 89
Fibonacci(100) // 堆栈溢出
Fibonacci(500) // 堆栈溢出
//尾递归优化
function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
if( n <= 1 ) {return ac2};
return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}
Fibonacci2(100) // 573147844013817200000
Fibonacci2(1000) // 7.0330367711422765e+208
Fibonacci2(10000) // Infinity
//在Javascript中,超出 1.7976931348623157E+103088 的数值即为Infinity,
//小于-1.7976931348623157E+103088 的数值为无穷小。
http://es6.ruanyifeng.com/#docs/function
http://www.ruanyifeng.com/blog/2015/04/tail-call.html
网友评论