当前位置:网站首页>浅谈ES6尾调优化
浅谈ES6尾调优化
2022-04-23 06:56:00 【fernwehseven】
前言
前两天笔试的时候遇到了这个问题,看了多篇博文之后终于理解了,在这里记录一下~
什么是尾调用
简单来说,一个函数的返回值是对另外一个函数的调用,这种情况就叫做尾调用。
function f1(n) {
return n * 2
}
function f2(n) {
return f1(n + 1) //line A
}
const res=f2(2))//line B
在以上代码中,f2的返回值是对f1的调用,这就是尾调用。
对尾调用的优化
首先我们要知道尾调优化是浏览器帮我们完成的工作,只要满足特定条件,这种优化就会被触发。
我们都知道:在代码执行时,会产生一个调用栈,调用某个函数时会将其压入栈,当它 return 后就会出栈。
以上面的代码为例我们对ES5和ES6的不同处理方案进行分析。
在ES5中:
- 调用函数f2,f2入栈,并记录下调用它的地方,以便知道返回值。
- 在尾部调用的函数f1会被推入新栈帧来表示调用,在入栈时记录下调用它的地方。当得到该函数的返回值时,f1执行结束,弹栈。
- f2得到了f1的返回值,f2的执行结束了,弹栈。
可以看出在这次调用中,每一个没有被用完的栈帧都保留在内存中。
观察可知,f1的执行结果不必先到达lineA,而是可以直接到达lineB。为什么呢?因为f2的返回值就是f1的返回值,没有在此基础上做任何操作。
在ES6中,就针对这种情况做了优化。
在ES6中:
缩减严格模式里尾调用栈帧的大小,如果满足以下条件,不再创建新栈帧,而是清空并重用当前函数的栈帧:
- 尾调用不再访问当前栈帧的变量(函数不是闭包)
- 尾调用的语句在函数的最后一行
- 尾调用的结果
直接作为函数的返回值
如何理解直接呢?例如下面的情况就不会做尾调优化
function f1(n) {
return n * 2
}
function f2(n) {
//在f2中并不是直接返回f1的结果,而是要进行加一的操作
return 1+f1(n + 1) //line A
}
const res=f2(2))//line B
原因也很好理解,因为f1的返回值不能直接到达lineB,而是要先到达lineA进行加1。
尾递归
什么是尾递归呢?其实就是尾调用的特殊形式:当尾调用是对自身的调用时,就是尾递归。
const sum = (n) => {
if (n <= 1) return n;
return n + sum(n-1)
}
sum(5)
这段代码的目的是用来计算1到5的和,但是很显然这种情况并不会做尾调优化,因为尾调函数不是直接return,而是要先加n。当n的数字增大的时候,因为之前的调用栈不能被释放掉,会造成栈溢出的问题。
我们可以利用ES6的尾调优化特性对上面的代码进行改写:
const sum = (n, preSum = 0) => {
if (n <= 1) return n + preSum
else {
// 现在的sum是preSum+n,递归算1~n-1的sum
return sum(n - 1, preSum + n)
}
}
sum(5)
这样理论上来说没有了最大栈限制的问题,但是我在实际测试(用chrome)是发现还是会有栈溢出的问题,查了之后说是有些浏览器还没支持这种优化。fine~TAT
版权声明
本文为[fernwehseven]所创,转载请带上原文链接,感谢
https://blog.csdn.net/fernwehseven/article/details/124174698
边栏推荐
- Anti shake and throttling
- Go语学习笔记 - 数组 | 从零开始Go语言
- NIH降血脂指南《your guide to lowering your Cholesterol with TLC》笔记(持续更新中)
- AAAI 2022招募讲者啦!!
- Intranet penetration series: dns2tcp of Intranet tunnel
- Chapter IV intangible assets
- Hierarchical output binary tree
- DataBinding的使用五
- 以下程序实现从字符串str中删除第i个字符开始的连续n个字
- Research on software security based on NLP (2)
猜你喜欢

每周leetcode - 06 数组专题 7~739~50~offer 62~26~189~9

Ribbon start process

Smart business card applet business card details page function implementation key code

Principle of sentinel integrating Nacos to update data dynamically

CTF attack and defense world brush questions 51-

【编程实践/嵌入式比赛】嵌入式比赛学习记录(一):TCP服务器和web界面的建立

惨了,搞坏了领导的机密文件,吐血分享备份文件的代码技巧

BUUCTF MISC刷題

feign如何集成hystrix

Redis--为什么字符串emstr的字符串长度是44字节上限?
随机推荐
1216_MISRA_C规范学习笔记_控制流的规则要求
sentinel集成nacos动态更新数据原理
几种智能机器人室内定位方法对比
面试学习路线
智能名片小程序名片详情页功能实现关键代码
Planification du mouvement du manipulateur dans l'assemblage 3c
Principle of sentinel integrating Nacos to update data dynamically
PHP generates short links: convert numbers to letters and letters to numbers
Ribbon启动流程
DataBinding的使用五
Concours de compétences en informatique en nuage - - première partie de l'environnement cloud privé openstack
惨了,搞坏了领导的机密文件,吐血分享备份文件的代码技巧
Implementation of promise all
Research on software security based on NLP (2)
LeetCode 1611. 使整数变为 0 的最少操作次数
Cloud computing skills competition -- the first part of openstack private cloud environment
数据库之Mysql——概述安装篇
SAP tr manual import system operation manual
CSV Column Extract列提取
Hump naming object