《理解 ES6》阅读整理:函数(Functions)(八)Tail Call Optimization
尾调用优化(Tail Call Optimization)
尾调用是指函数的最后一条语句是函数调用,比如下面的代码:
function doSomething() {
return doSomethingElse();
}
在ES5中,尾调用和其他形式的函数调用一样:脚本引擎创建一个新的函数栈帧并且压在当前调用的函数的栈帧上面。也就是说,在整个函数栈上,每一个函数栈帧都会被保存,这有可能造成调用栈占用内存过大甚至溢出。
尾递归在ES6中有何不同(How Tail Call are Different in ECMAScript6)
在ES6中,strict模式下,满足以下条件,尾调用优化会开启,此时引擎不会创建一个新的栈帧,而是清除当前栈帧的数据并复用:
(1、尾调用函数不需要访问当前栈帧中的变量
(2、尾调用返回后,函数没有语句需要继续执行
(3、尾调用的结果就是函数的返回值
下面例子中的函数就可以使用尾调用优化:
"use strict";
function doSomething() {
return doSomethingElse();
}
然而下面例子中的函数不能使用尾调用优化,因为尾调用的结果不是函数的返回值:
"use strict";
function doSomething() {
doSomethingElse();
}
尾调用返回后,如果函数仍然有语句要执行,也是不能使用尾调用优化的:
"use strict";
function doSomething() {
return 1 + doSomethingElse();
}
尾调用函数如果是闭包函数,也不能使用尾调用优化:
"use strict";
function doSomething() {
var num = 1;
var func = () => num;
return func();
}
如何利用尾调用优化(How to Harness Tail Call Optimization)
尾调用优化主要用在递归函数中,通常能带来显著的效果。看一个递归计算阶乘的函数:
function factorial(n) {
if (n <= 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
很明显,上面的代码并不能使用尾调用优化,因为factorial(n-1)返回后,仍然有语句要继续执行。但是我们可以改写这个函数,使其能够利用尾调用优化特性:
function factorial(n, p = 1) {
if (n <= 1) {
return 1 * p;
} else {
let result = n * p;
return factorial(n - 1, result);
}
}
如和改写递归函数以便利用尾调用优化是需要技巧的。如果可以,应该充分利用引擎的尾调用优化特性来优化递归函数。
《理解 ES6》阅读整理:函数(Functions)(八)Tail Call Optimization的更多相关文章
- 《理解 ES6》阅读整理:函数(Functions)(五)Name Property
名字属性(The name Property) 在JavaScript中识别函数是有挑战性的,因为你可以使用各种方式来定义一个函数.匿名函数表达式的流行使用导致函数调试困难,在栈信息中难以找出函数名. ...
- 《理解 ES6》阅读整理:函数(Functions)(一)Default Parameter Values
对于任何语言来说,函数都是一个重要的组成部分.在ES6以前,从JavaScript被创建以来,函数一直没有大的改动,留下了一堆的问题和很微妙的行为,导致在JavaScript中使用函数时很容易出现错误 ...
- 深入理解ES6箭头函数中的this
简要介绍:箭头函数中的this,指向与一般function定义的函数不同,比较容易绕晕,箭头函数this的定义:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定. 1.何为定义时 ...
- ES6 入门系列 - 函数的扩展
1函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log( ...
- es6中的函数
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面. function log(x, y = 'World') { console.log(x, y); } log('Hello') // ...
- asp.net MVC helper 和自定义函数@functions小结
asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...
- asp.net MVC 自定义@helper 和自定义函数@functions小结
asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...
- 《javascript个人理解,个人整理。》
万事开头难. 本人做前端工程师,已几年,没有特别大的,已文字方式去做总结. 前段时间,早已经想好,但是迟迟没有去下笔!好在现在陆陆续续的写下去. 我知道这是一个很大的工程,但是我还是想做下去,不为别的 ...
- ES6知识整理(4)--数组的扩展
最近工作比较忙,基本每天都会加班到很晚.处理一些客户端兼容问题以及提升用户体验的优化.也将近一周没更文了,现在继续es6的学习总结. 上篇回顾 ES6知识整理(三)--函数的扩展 扩展运算符 形式是3 ...
随机推荐
- Spring HTTP下载
(1)HTTP 协议可以在客户端和服务器之间传递任何类型的文件. HTTP协议下载文档到客户端时候, 必须通过响应头Content-Type设置文件类型. 例如: contentType=text/h ...
- Oracle 左连接、右连接、全外连接、(+)号作用
分类: Oracle Oracle 外连接 (1)左外连接 (左边的表不加限制) (2)右外连接(右边的表不加限制) (3)全外连接(左右两表都不加限制) 外连接(Outer ...
- JS编写全选,复选按钮
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- 自定义View(二)增加View的属性
增加View的属性有两种方法 1.在View类中添加 2.在xml资源文件中添加 一.在View类中添加 例:实现一个带文字的图片 public class MyView exten ...
- oracle 第一章总结
sysdba: 即数据库管理员,权限包括:打开数据库服务器.关闭数据库服务器.备份数据库.恢复数据库.日志归档.会话限制.管理功能.创建数据库.sys用户必须用 sysdba身份才能登录,syste ...
- solaris安装oracle遇INS 30131 错误
安装11.2.0.4,报错: [FATAL] [INS-30131] Initial setup required for the execution of installer validations ...
- Yii2 中禁用csrf校验
Yii2 默认开启csrf校验,但是有些时候确实不需要校验,比如对外提供API 一般做法直接在xxController中增加属性: public $enableCsrfValidation = fal ...
- FreeSWITCH 1.2.5.3 Step by Step Install
Ubuntu: apt-get -y install build-essential automake autoconf git-core wget libtool apt-get -y instal ...
- Keepalived 配置实例
Keepalived 是一款轻量级HA集群应用,它的设计初衷是为了做LVS集群的HA,即探测LVS健康情况,从而进行主备切换,不仅如此,还能够探测LVS代理的后端主机的健康状况,动态修改LVS转发规则 ...
- UNIX 系统调用函数errno返回值搜集(in updating )
当Unix系统级函数遇到错误时,它们会典型地返回-1,并设置全局整数变量errno来表示什么出错了 阅读redis源码的时候,发现如果对系统级函数出错时的errno比较熟悉,写起程序来会游刃有余不少. ...