🌰 示例
递
和 归
是两个动作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
function factorial(n) { if (n === 1) { console.trace() return 1 }
return n * factorial(n - 1) }
factorial(3) factorial(4)
|
🍐 factorial(4)
的栈信息
使用 console.trace()
发现当 n = 1
时, 栈里有 4次 的函数调用。
给一个足够大的数字会发生爆栈
尾递归、尾调用 PTC
- 尾调用即为函数取个别名,互相调用。这样互相出栈进栈,可以减低爆栈的风险
- 尾递归则是在函数最后一步操作调用本身
为什么不是尾递归
在示例中 factorial
确实是在最后一行 return 调用自己,为什么不能称之为尾递归
1 2 3 4 5 6 7 8
| function factorial(n) { if (n === 1) { return 1 }
return n * factorial(n - 1) }
|
修改成尾递归
1 2 3 4 5 6 7 8
| function factorial(n, total) { if (n === 1) { return total }
return factorial(n - 1, n * (n - 1)) }
|
while 循环
递归本质上还是循环,直接用 while 拉平即可
1 2 3 4 5 6
| let start = 10 let count = 1 while (start > 1) { count *= start-- } console.log(count)
|
蹦床函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function sum(n, toal = 0) { if (n === 0) return toal
return sum.bind(null, n - 1, n + toal) }
function trampoline(f) { while (f instanceof Function) { f = f() } return f }
|