编译流程
- 解析/语法分析
- 代码生成
- 分词/词法分析
程序处理的三大角色
引擎
-
从头到尾负责整个 JavaScript 程序的编译及执行过程。
-
变量赋值查询
-
LHS
-
成功?
- 查找到赋值操作的目标(容器)
-
失败?
-
严格模式
- 抛出 ReferenceError 异常
-
非严格模式
- 自动隐式地创建一个全局变量
-
-
-
RHS
-
成功?
- 查找到赋值操作的源头并获取值
-
失败?
- 抛出 ReferenceError 异常
-
-
-
编译器
-
负责语法分析及代码生成
-
编译阶段中的一部分工作就是找到所有的 声明,并用合适的作用域将它们关联起来
-
提升
-
无论作用域中的声明出现在什么地方,包括变量和函数在内的所有声明都将在代码本身被执行前首先进行处理。
- 1、函数声明会被提升,但是函数表达式(var foo=function(){})却不会被提升。
- 2、函数会首先被提升,然后才是变量
- 3、重复的var声明会被忽略,但是重复的函数声明不会被忽略
-
-
作用域
-
负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问。
-
词法作用域(静态作用域)
-
特性
- 1、由书写代码时函数声明的位置来决定的
- 2、关注函数在何处声明
-
函数作用域
- 匿名和具名
- 立即执行函数表达式IFFE
-
块级作用域
- let和const
- try/catch
- with/eval
-
-
动态作用域
- 1、由函数运行时所确定的
- 2、关注函数从何处调用
-
-
闭包
-
概念
- 当函数在当前词法作用 域之外执行。但可以记住并访问所在的词法作用域时,就产生了闭包。
-
哪里使用?
-
循环和闭包
- for (let i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
- for (let i=1; i<=5; i++) {
-
回调函数
- 在定时器、事件监听器、Ajax 请求、跨窗口通信、Web Workers 或者任何其他的异步(或者同步)任务中,只要使用了回调函数,实际上就是在使用闭包!
-
-
应用
- 模块
- 柯里化
-