编译原理
javaScript与传统的编译语言不同,它不是提前编译的,但是它的引擎进行编译的步骤和别的传统编译语言非常相似,在传统编译语言中,一段程序的源代码在执行之前会经历三个步骤,统称为编译。
- 分词/词法分析:将字符组成的字符串分解成有意义的代码块,这些代码块叫词法单元,比如
var a = 1 ;
会被分解成var,a,=,1,;。 - 解析/语法分析:将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为“抽象语法树”(Abstract Syntax Tree,AST),AST是程序语法结构的一种抽象表示,树上的每个节点都表示源代码中的一种结构,有兴趣的同学可以在这里感受一下:
- 代码生成:将 AST 转换为可执行代码的过程被称为代码生成,简单来说就是有某种方法可以将 var a = 2; 的 AST 转化为一组机器指令,用来创建一个叫作 a 的变量(包括分配内存等),并将一个值储存在 a 中。
理解作用域
先认识几个概念~~
引擎
编译器
作用域
下面我们将以var a = 2 ;
举例 。
- 遇到 var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。如果是编译器会忽略该声明,继续进行编译;否则它会要求作用域在当前作用域的集合中声明一个新的变量,并命名为 a。(预编译)
- 接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理 a = 2 这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作 a 的变量。如果是,引擎就会使用这个变量;果否,引擎会继续查找该变量。(解释执行)
引擎会为变量 a 进行 LHS 查询。另外一个查找的类型叫作 RHS 查询。
LHS 查询
RHS 查询
检验一下LHS 查询和RHS 查询的理解程度。
var b = a;
return a + b;
}
var c = foo( 2 );
1. 找到其中所有的 LHS 查询。(这里有 3 处!)
2. 找到其中所有的 RHS 查询。(这里有 4 处!)
答案:
1. 找出所有的 LHS 查询(这里有 3 处!)
c = ..;、a = 2(隐式变量分配)、b = ..
2. 找出所有的 RHS 查询(这里有 4 处!)
foo(2..、= a;、a ..、.. b
作用域嵌套
把作用域链比喻成一个建筑
LHS 和 RHS 引用都会在当前楼层进行查找,如果没有找到,就会坐电梯前往上一层楼,如果还是没有找到就继续向上,以此类推。一旦抵达顶层(全局作用域),可能找到了你所需的变量,也可能没找到,但无论如何查找过程都将停止。
不成功的 RHS 引用会导致抛出 ReferenceError 异常。不成功的 LHS 引用会导致自动隐式地创建一个全局变量(非严格模式下)。
总结
作用域定义为一套规则,这套规则用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符名称进行变量查找。
参考文献
《你不知道的JavaScript》
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!