尾调用
在编码过程中,经常涉及到函数调用函数,例如:
function a() {
b();
}
function b() {}
我们每次调用函数,都会在在内存中记录一个“调用帧”又成为“栈帧空间”
在上述例子中,调用a()
函数,会在内存中记录一个调用栈,然后继续调用b()
函数,此时在内存中又会记录一个调用帧,等到b()
函数运行结束,调用帧a
、b
的内存才会释放。
我们可以利用“尾调用”来释放调用帧内存
function a() {
return b();
}
function b() {}
上述代码中,在函数的最后一步调用了b()
函数,外层函数内存直接被释放,确认代之的是b()
函数内存被创建,从复杂度来看,普通调用复杂度O(n)
,尾调用复杂度O(1)
尾调用并不是函数中的最后一行,而是最后一步,在下面的例子中,也可以实现尾调用
function a(n) {
if(n === 5){
return b(); // 尾调用
}
return c(); // 尾调用
}
尾递归
递归函数就是函数调用自身,正常的递归函数会进行深层调用,每次调用函数都会创建内存,也就是上面所说的调用帧,直到递归函数执行完毕,内存才会被释放,如果递归函数层级过深,记录栈帧过多,会导致栈溢出错误。
我们可以利用尾调用来优化并释放内存,下面是一个尾递归函数
/* 尾递归 */
function tailRecur(n, res) {
// 终止条件
if (n === 0) return res;
// 尾递归调用
return tailRecur(n - 1, res + n);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。