在传统编译语言的流程中,程序中的一段源代码在执行之前会经历三个步骤,统称为编译。1、分词/词法分析(Tokenizing/Lexing):
这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元(token)。2、解析/语法分析(Parsing):
这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为抽象语法树(Abstract Syntax Tree),简称AST。3、代码生成:
将 AST 转换为可执行代码的过程称被称为代码生成。注意:任何 JavaScript 代码片段在执行前都要进行编译(通常就在执行前)。
从头到尾负责整个 JavaScript 程序的编译及执行过程。2、编译器:
负责语法分析及代码生成等脏活累活。3、作用域:
负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。怎样协同工作将 var a = 2; 分解,看看引擎它们是如何协同工作的。
遇到 var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。如果是,编译器会忽略该声明,继续进行编译;否则它会要求作用域在当前作用域的集合中声明一个新的变量,并命名为 a。1.2、为引擎生成运行时所需的代码
接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理 a = 2 这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作 a 的变量。如果是,引擎就会使用这个变量;如果否,引擎会继续查找该变量。2、引擎:
注释:RHS 查询与简单地查找某个变量的值别无二致,而 LHS 查询则是试图找到变量的容器本身,从而可以对其赋值。作用域嵌套
遍历嵌套作用域链的规则很简单:引擎从当前的执行作用域开始查找变量,如果找不到,就向上一级继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找过程都会停止。异常为什么区分 LHS 和 RHS 是一件重要的事情?
因为在变量还没有声明(在任何作用域中都无法找到该变量)的情况下,这两种查询的行为是不一样的。1、首先 LHS 以及 RHS 到底是什么意思?
LHS和RHS:是JavaScript引擎的两种查找类型,含义是赋值操作的左侧与右侧。LHS:对哪个赋值就对哪个进行LHS引用,可以理解为赋值操作的目标。
function foo(a) {
var b = a;
return a + b;
}
var c = foo( 2 );
function foo(a) {
console.log( a + b );
b = a;
}
foo( 2 );
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |