- 编译:
传统流程:
步骤一:分词/词法分析(Tokenizing/Lexing):将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元;空格是否会被当作词法单元,取决于空格在这门语言中是否具有意义;词法单元的识别是通过有状态还是无状态的方式进行的,即调用的是有状态的解析规则,那么这个过程就被称为词法分析。(例如:var a = 2;。这段程序通常会被分解成为下面这些词法单元:var、a、=、2 、;。)
步骤二:解析/语法分析(Parsing):将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树,即“抽象语法树”(Abstract Syntax Tree,AST)。
步骤三:代码生成:将AST转换为可执行代码的过程。
JavaScript引擎:大部分情况下编译发生在代码执行前的几微秒,甚至更短的时间内。(用了各种办法,比如JIT,可以延迟编译甚至实施重编译等,来保证性能最佳。) - 不同角色 :
作用域类型:词法作用域(定义在词法阶段的作用域)、动态作用域。
变量的赋值操作:会执行两个动作,首先如果该变量之前没有声明过,则编译器会在当前作用域中声明该变量(若已声明,则忽略这一步骤),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值,反之则会抛出异常。
在运行时引擎在作用域中查找变量过程的类型可分为:
LHS:寻找赋值操作的目标(获取值的)。–目标引用(查询)
RHS:寻找赋值操作的源头(给予值的)。–源头引用(查询)
区分LHS和RHS很重要的原因: 因为在变量还没有声明(在任何作用域中都无法找到该变量)的情况下,这两种查询的行为是不一样的。
对于RHS查询来说:在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常;若对找到的变量的值进行不合理的操作时,引擎则会抛出另外一种类型的异常,即TypeError异常。
对于LHS查询来说:如果在全局作用域中也无法找到目标变量,当程序运行在非“严格模式”下时,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎;当程序运行在“严格模式”下时,并不会创建并返回一个全局变量,引擎会抛出ReferenceError异常。 - 作用域嵌套:当一个块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套。(因此在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量或抵达最外层的作用域也就是全局作用域时,无论找到还是没找到,查找过程都会停止。)
- 异常:
TypeError异常:表示作用域判别成功了,但是对结果的操作是非法或不合理的。
ReferenceError:表示与作用域判别失败相关。 - 啊这:
- 啊这:
- 啊这:
- 啊这: