图解尾调用优化

图解尾调用优化

尾调用

啥是尾调用?html

尾调用就是函数的最后一个步骤调用另外一个函数异步

比方说:函数

20190307171547.png

函数在调用的时候会在调用栈中 push 一个调用帧,每次执行完函数都会逐一弹出调用帧知道全部函数执行完毕,调用栈被清空:oop

调用栈中的同步代码post

function f1() { console.log('🍎') }
function f2() { f1() }
function f3() { f2() }

f3()

调用栈以下图:优化

  • 首先执行 script ,将 main 主程序推入调用栈中并执行,发现须要调用 f3
  • 将 f3 函数推入调用栈中,执行 f3,发现须要调用 f2
  • 将 f2 函数推入调用栈中,执行 f2, 发现须要调用 f1
  • 将 f1 推入调用栈中,执行 f1,发现须要调用 console.log 方法
  • 推入 console.log 并打印结果执行完毕
  • 弹出 consoole.log
  • 弹出 f1
  • 弹出 f2
  • 弹出 f3
  • 弹出 main,代码执行完毕

调用栈中的异步代码spa

以 setTimeout 为例:code

console.log('1')
setTimeout(function() {
    console.log('3)
}, 5000)
console.log('2')

调用栈见下图:htm

  • 执行代码推入 script 代码 main 并执行,发现须要执行 console.log
  • 将 console.log 推入调用栈
  • 执行 console.log 打印 1 弹出调用栈
  • 发现 setTimeout 将等待执行的回调函数推入宏任务列表,将 setTimeout 弹出调用栈
  • 继续执行代码发现须要执行 console.log 将任务推入调用栈
  • 执行 console.log 打印 2 并弹出调用栈
  • script 代码 main 执行完毕,弹出调用栈
  • 同步代码执行完毕,查看宏任务列表发现须要执行 console.log
  • 延迟 5s 将 console.log 推入调用栈
  • 执行 console.log 并打印 2
  • 最后将 console.log 弹出调用栈,代码执行完毕

尾调用优化

每次在函数被调用的时候,内存都会保存调用帧。尾调用由于是函数的最后一步,所以并不须要外层函数的调用帧。咱们只须要将最后须要执行另一个函数以前用 return 操做符显式代表"再也不须要此函数"便可blog

20190309013011.png

before

20190309013038.png

after

注意必须使用严格模式

在执行过程当中,调用栈的调用帧永远只有一条,这样就能够节省很大一部份内存

参考:

相关文章
相关标签/搜索