[TOC]
>[success] # 尾调用优化
~~~
'尾调用优化'使用场景,一般在'递归'时使用会有显著效果,在'ES6'中对函数最有趣的改动或许就是一项
'引擎优化',它改变了'尾部调用'的系统。'尾调用'指的是调用函数的语句是'另一个函数的最后语句',有3点,
符合这'3'点就是达成了'尾调用优化'
1. 尾调用不能引用当前栈帧中的变量(意味着'该函数不能是闭包')
2. 进行尾调用的函数在'尾调用返回结果后不能做额外操作'
3. 尾调用的结果作为当前函数的返回值
~~~
~~~
function doSomething() {
return doSomethingElse() // 尾调用
}
~~~
<br/>
>[danger] ## 错误尾调用优化案例
1. 没有return
~~~
"use strict"
function doSomething() {
doSomethingElse() // 未被优化:缺少 return
}
~~~
2. 在return时候还进行加法操作
~~~
"use strict"
function doSomething() {
return 1 + doSomethingElse() // 未被优化:在返回之后还要执行加法
}
~~~
3. 将函数调用的结果储存在一个变量上,之后才返回了 结果
~~~
"use strict"
function doSomething() {
let result = doSomethingElse() // 未被优化:调用并不在尾部
return result
}
~~~
4. 闭包能够访问上层作用域的变量,会导致尾 调用优化被关闭
~~~
"use strict";
function doSomething() {
let num = 1,
func = () => num
return func() // 未被优化:此函数是闭包
}
~~~
<br/>
>[success] ## 如何控制尾调用优化
~~~
在实践中,'尾调用优化在后台进行',所以不必对此考虑太多,除非要尽力去优化一个函数。尾调用优化的主要用
例是在'递归函数'中,而且在其中的优化具有最大效果。考虑以下计算阶乘的函数:
~~~
优化前:
~~~
// 阶乘递归
function factorial(n) {
if (n <= 1) {
return 1
} else {
// 未被优化:在返回之后还要执行乘法
return n * factorial(n - 1)
}
}
~~~
优化后:
~~~
function factorial(n, p = 1) {
if (n <= 1) {
return 1 * p
} else {
let result = n * p
// 被优化
return factorial(n - 1, result)
}
}
~~~
- Javascript基础篇
- Array数组
- 数组插入值
- filter()
- forEach()
- push()
- pop()
- unshift()
- shift()
- valueOf()
- 面向对象思想
- Javascript 面向对象编程(一):封装
- Javascript面向对象编程(二):构造函数的继承
- Javascript面向对象编程(三):非构造函数的继承
- 解构
- 数组的解构赋值
- 对象的解构赋值
- 函数参数解构
- 字符串的解构赋值
- 数值和布尔值的解构赋值
- 圆括号问题
- 字符串.
- split()
- charAt()
- charCodeAt()
- concat()
- indexOf()
- lastIndexOf()
- match()
- replace()
- includes()
- 初识递归
- 渲染ul-li树形结构
- 异步函数解决方案
- 1. callback回调函数
- 2. ES6 - Promise
- JavaScript高级程序设计(书)
- 在html中使用JavaScript
- script标签的位置
- 延迟脚本
- 异步脚本
- <noscript>元素
- 基本概念
- 严格模式
- 变量详解
- 数据类型
- typeof操作符
- undefined类型
- Null类型
- Boolean类型
- Number类型
- 深入了解ES6(书)
- var 、let 、 const
- 字符串与正则表达式
- 字符串
- 正则表达式
- 函数
- 函数形参默认值
- 使用不具名参数
- 函数构造器的增强能力
- 扩展运算符
- name属性
- 明确函数的多重用途
- 块级函数
- 箭头函数
- 尾调用优化
- 扩展的对象功能
- 对象类别
- 对象字面量语法的扩展
- ES6对象新增方法
- 重复的对象属性
- 自有属性的枚举顺序
- 更强大的原型
- 解构:更方便的数据访问
- 为什么要用解构?
- 对象解构
- 数组解构
- 混合解构
- 参数解构
- Symbol与Symbol属性
- 创建Symbol
- Symbol的使用方法
- Symbol全局私有属性
- Symbol与类型强制转换
- Symbol属性检索
- Symbol的一些构造方法
- Set集合与Map集合
- Set集合
- Weak Set集合(弱引用Set集合)
- Map集合
- JS标准内置对象
- Object 构造函数及属性
- Object 构造方法
- Symbol 内建对象类的函数及属性
- Set 构造函数及属性
- Weak Set 构造函数及属性
- JS杂项
- 类数组对象
- Class类的理解和使用