BuZhiDaoen 2019-06-25
引擎:负责整个js程序的编译和执行过程
编译器:负责语法分析和代码生成
作用域:收集和维护一系列查询(由所有声明的标识符组成)
【例子:声明一个变量并赋值 var a = value;】
Step1.编译器对该程序段分解成词法单元 "var" 、"a"、 "="、 "value"、";"
Step2.编译器对以上的词法单元解析成一个树结构(抽象语法树AST)
javascript的语法解析器Espsrima提供了一个在线解析的工具
在过程中,编译器询问作用域是否已经存在一个以"a"命名的变量在同一个作用域的集合中?若YES -> 编译器忽略该声明,继续编译;若NO -> 编译器要求作用域在当前作用域的集合中声明一个新变量,命名为a
Step3.编译器生成处理 赋值操作“a = 2”的代码
Step4.引擎运行step3生成的代码时会询问作用域,在当前作用域的集合中是否存在一个叫"a"的变量?若YES -> 引擎使用变量a ->Step5;若NO -> 引擎沿着作用域链继续查找变量a ->Step6
Step5.引擎执行编译器生成的代码,把2赋值给变量a
Step6.引擎抛出一个异常
【总结】变量的赋值会经过两个阶段:
1.编译器在作用域中声明一个变量(若之前未声明过)
2.运行时引擎在作用域中查找该变量
【扩展】
Step4中引擎查询变量有两种类型:LHS 和 RHS
LHS: 找到变量的容器本身
RHS:找到变量的值
例子:
function foo(a){ var b = a; return a+b } var c = foo(2); //在该例子中,LHS有:a = 2 、c= 、b= //RHS有:=foo(2)、 =a、a+、+b