糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > JavaScript简餐——函数尾调用优化

JavaScript简餐——函数尾调用优化

时间:2021-07-11 15:27:12

相关推荐

JavaScript简餐——函数尾调用优化

文章目录

前言一、认识尾调用优化二、尾调用优化的条件三、尾调用优化实例总结

前言

写本《JavaScript简餐》系列文章的目的是记录在阅读学习《JavaScript高级程序设计(第4版)》一书时出现的各个知识点。虽是对读书的笔记和总结,但是希望它轻量、简洁、犀利,不会引起阅读疲劳,可以在碎片化时间和闲暇之余轻巧地沐浴一下知识点。每篇文章只针对一个小部分进行讲解式的梳理,来达到个人复习总结和分享知识的目的。


一、认识尾调用优化

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

function Function_A() {return Function_B(); // 尾调用}

在ES6优化之前,执行这个例子会在内存中发生如下操作: 执行到Function_A函数体,第一个栈帧被推到栈上。执行到Function_A的return处时必须先计算Function_B。执行到Function_B函数体,第二个栈帧被推到栈上。Function_B计算返回值。Function_B将返回值传回Function_A,然后Function_A返回最终值。将栈帧弹出栈外。

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

执行到Function_A函数体,第一个栈帧被推到栈上。执行到Function_A的return处时必须先计算Function_B。引擎发现此时把第一个栈帧弹出栈外也没有问题,因为Function_B的返回值也是Function_A的返回值。弹出Function_A的栈帧。执行到Function_B函数体,栈帧被推到栈上。执行Function_B函数体,计算其返回值。将Function_B的栈帧弹出栈外。

很明显,第一种情况下每多调用一次嵌套函数,就会多增加一个栈帧。而第二种情况下无论调用多少次嵌套函数,都只有一个栈帧。这就是ES6尾调用优化的关键:如果函数的逻辑允许基于尾调用将其销毁,则引擎就会那么做。


二、尾调用优化的条件

尾调用优化的条件就是确定外部栈帧真的没有必要存在了,其条件如下: 代码在严格模式下执行外部函数的返回值是对尾调用函数的调用尾调用函数返回后不需要执行额外的逻辑尾调用函数不是引用外部函数作用域中自由变量的闭包

下面来看一下违反条件的例子

("use strict");// 不满足条件,尾调用没有返回function Function_A() {Function_B();}// 不满足条件,尾调用没有直接返回function Function_A() {let result = Function_B();return result;}// 不满足条件,尾调用执行了额外的逻辑function Function_A() {Function_B().toString();}// 不满足条件,尾调用是一个闭包function Function_A() {let name = "Lucy";return function Function_B() {return name;};}


三、尾调用优化实例

来看一个递归计算斐波那契数列的例子:

function fib(n) {if (n < 2) {return n;}return fib(n - 1) + fib(n - 2);}

显然这个函数不符合尾调用优化条件,因为在尾调用函数返回值执行了相加操作,即执行了额外的逻辑。为此,我们可以使用两个嵌套的函数,外部函数作为基础框架,内部函数执行递归:

("use strict");// 基础框架function fib(n) {return fibItem(0, 1, n);}// 执行递归function fibItem(a, b, n) {if (n === 0) {return a;}return fibItem(b, a + b, n - 1);}

这样重构之后,就可以满足尾调用优化的所有条件了。


总结

以上就是今天要讲的内容,今天简单介绍了一下尾调用优化、进行尾调用优化的条件以及一个尾调用优化实例。下一篇开始我们来讲一下ES6中新增的Promise引用类型,开始优雅地组织异步逻辑。撒花~

如果觉得《JavaScript简餐——函数尾调用优化》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。