编程语言基本功能:能够储存变量中的值,并在之后对其进行访问或修改
设计一套规则来存储变量,并在之后方便找到,这个规则就是作用域
1.1 编译原理
传统编译语言,源代码执行后经历三个步骤,成为编译
-
分词/词法解析
将字符串分解成有意义的代码块(词法单元)
-
解析/语法解析
将词法单元流转换成由元素逐级嵌套所组成的代表程序语法结构的树(抽象语法树)
-
代码生成
将
AST
转换成可执行代码,与语言、目标平台相关
简单说就是某种方法可以将var a = 2;的AST
转换为一组机器指令,用来创建一个a的变量(包括分配内存等),并一个值储存在a中
JavaScript引擎更加复杂,在语法解析和代码生成阶段有特定步骤对运行性能进行优化
任何js
代码片段在执行前都要进行编译(执行前的几微秒),并且通常会立即执行
1.2 理解作用域
- 引擎:负责整个JavaScript程序的编译和执行结果
- 编译器:负责语法解析及代码生成等
- 作用域:负责收集并维护由所有声明的标识符(常量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限
将var a = 2;
分解
编译器首先将程序分解为词法单元,再将词法单元解析为一个树结构
赋值操作两个动作:编译器声明变量,运行时引擎查找变量
- 遇到var a,编译器在作用域中查找该变量是否存在,存在编译,不存在声明
- 为引擎生成运行时所需代码,处理a=2这个赋值操作;在当前作用域中查找此变量,找不到继续往上找
引擎最终找到a变量,并将2赋值给a
LHS
引用和RHS
引用
LHS
和RHS
含义是:赋值操作的左侧和右侧,更好的理解是:赋值操作的目标是谁,谁是赋值操作的源头
RHS(retrieve his source value)
查找某个变量的值,获取,LHS
试图找到变量的容器本身,对变量进行赋值
function foo(a) {
var b = a
return a + b
}
var c = foo(2)
// LHS 1.c = .. 2.隐式变量赋值a=2 3.b=...
// RHS 1.foo(2) 2. = a 3.a+.. 4. ...+b
1.3 作用域嵌套
在当前域中无法找到变量时,引擎会继续项外层嵌套的作用域中去查找
1.4 异常
区分LHS
和RHS
作用,在变量未声明前,查询行为不一样
RHS
引用找不到变量时,引擎会抛出ReferenceError
,LHS
引用找不到变量时,会在全局作用域创建,在严格模式下,也会抛出ReferenceError
异常
网友评论