Javascript中的尾调用优化

什么是尾调用

ES6新增了一项内存管理机制,让Javascript引擎可以在满足条件时可以重用栈帧。这项优化非常适合“尾调用”,即外部函数的返回值是一个内部函数的返回值。

function outerFunction() {
      return innerFunction()
    }

在ES6优化之前,执行这个例子会在内存中发生以下操作:

  • 执行到outerFunction函数体,第一个栈帧被推到栈上;

  • 执行outerFunction函数体,到return语句。计算返回值必须先计算innerFunction;

  • 执行到innerFunction函数体,第二个栈帧被推到栈上;

  • 执行innerFunction函数体,计算其返回值;

  • 将返回值传回outerFunction,然后outerFunction再返回值;

  • 将栈帧弹出栈外
    在ES6优化之后,执行这个例子会在内存中发生以下操作:

  • 执行到outerFunction函数体,第一个栈帧被推到栈上;

  • 执行outerFunction函数体,到return语句。计算返回值必须先计算innerFunction;

  • 引擎发现把第一个栈帧弹出栈外也没问题,因为innerFunction的返回值也就是outerFunction的返回值;

  • 弹出outerFunction的栈帧

  • 执行到innerFunction函数体,栈帧被推到栈上

  • 执行innerFunction函数体,计算返回值

  • 将innerFunction的栈帧弹出栈外

尾调用优化条件

尾调用优化条件是确定外部栈帧真的没有存在的必要了。其条件有:

  • 代码在严格模式下进行;
  • 外部函数的返回值是对尾调用函数的调用;
  • 尾调用函数返回后不需要执行额外的逻辑;
  • 尾调用函数不是引用外部函数作用域中变量的闭包;
	// 无优化,尾调用没有返回
    function outerFunction() {
      innerFunction()
    }
    //无优化,尾调用没有直接返回
    function outerFunction(){
      let innerFunctionResult = innerFunction()
      return innerFunctionResult
    }
    // 无优化,尾调用返回后还要转型为字符串
    function outerFunction(){
      return innerFunction().toString()
    }
    //无优化,尾调用是个闭包
    function outerFunction() {
      let foo = 'hello'
      function innerFunction() { return foo }
      return innerFunction()
    }

    'use strict'
    //有优化:栈帧被销毁前执行参数计算
    function outerFunction(a, b) {
      return innerFunction(a + b)
    }
    // 有优化,初始返回值不涉及栈帧
    function outerFunction(a, b){
      if(a < b) {
        return a
      }
      return innerFunction()
    }
    // 有优化,两个内部函数都在尾部
    function outerFunction(condition){
      return condition ? innerFunctionA() : innerFunctionB()
    }

尾调用优化代码

通过把简单的递归函数转换为优化的代码来理解尾调用优化。

递归函数形式求解斐波拉契数列
function fib(n) {
  if (n < 2){
    return 1
  }
  return fib(n - 1) + fib(n - 2)
}

这个函数不满足尾调用的条件,因为最后的操作还有加法。可以将其重构为满足优化条件的形式。为此可以使用两个嵌套函数,外层函数作为基础框架,内层函数执行递归:

'use strict'
// 基础框架
function fib(n){
  return fibImp(0,1,n)
}
function fibImp(a, b, n) {
  if(n === 0) {
    return a
  }
  return fibImp(b, a + b, n - 1)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值