编译原理
传统编译语言
- 词法分析:将由字符组成的字符串分解成(对编译语言来说)有意义的代码块,这些代码块被称为词法单元。
- 解析/语法分析:将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树,即“抽象语法树”(abstract syntax tree,AST)。
- 代码生成:将AST转换成可执行代码的过程被称为代码生成。这个过程与语言、目标平台等息息相关。
相比只有三个步骤的语言的编译器,javascript引擎要复杂的多。例如,在语法分析和代码生成阶段有特定的步骤来对运行性能进行优化,包括对冗余元素进行优化。简单的说,任何javascript代码片段在执行前都要进行编译(通常就在执行前)
理解作用域
- 程序处理过程中的角色:
1.引擎
从头到尾负责整个javascript程序的编译和执行过程
2.编译器
负责语法分析及代码生成等脏活累活
3.作用域
负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
简单的说:作用域是一套规则,用于确定在何处以及如何查找变量(标识符) - 变量的赋值操作
var a=2;
会执行两个动作,首先编译器会在当前作用域声明一个变量(如果之前没有声明过),然后运行时引擎会在作用域中查找该变量,如果能够找到就会对他赋值:
1.编译器在编译过程的第二步中生成了代码,引擎执行它时,会通过查找变量来判断它是否以声明过,查找的过程由作用域进行协助。
2.引擎有两种查找类型:(1)如果查找的目的是对变量进行赋值,那么就会使用LHS查询,(2) 如果目的是获取变量的值,就会使用RHS查询。这两种查询都会在当前执行作用域中开始,如果他们没有找到所需的标识符,就会向上级作用域继续查找目标标识符,最后抵达全局作用域,这时候无论找不找的到都将停止。
3.不成功的RHS引用会导致抛出ReferenceError异常:在所有嵌套的作用域中遍寻不到所需的变量。不成功的LHS引用会导致自动隐式创建一个全局变量(非严格模式下),该变量使用LHS引用的目标作为标识符,或者抛出ReferenceError异常(严格模式下)
4.如果RHS查询找到了一个变量,但你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或者引用null或undefined类型的值中的属性,那么引擎会抛出另外一种类型的异常,叫做TypeError。ReferenceError同作用域判别的失败相关,而TypeError则代表作用域判别成功了,但是对结果的操作是非法或不合理的