传统编译语言中,程序中的一段源代码在执行前会经过3个步骤,这三个步骤统称为编译:
1。分词/词法分析: 将代码分割分解成对这门语言有意义的代码块 2。解析/语法分析: 将这些代码块组成一个程序语法树,有点类似与浏览器解析时候生成dom树 3。代码生成: 转化为机器可识别的代码
例,var a = 2
这个赋值操作我们一般是这样理解: 申明一个a变量,为它分配一个内存,然后将2的值保存进内存里面 编译器和引擎的实际操作是: 当遇到var a 的时候,编译器会问作用域,是否已经存在a这个变量,如果没有就在作用域中声明a变量 如果有就继续下一步(同级作用域中后面声明的同名变量会被忽略,我之前的理解是后面声明的同名变量会覆盖前面声明的变量,其实这个要分两块来理解,一个是声明部分,一个是赋值部分;准确来说应该是:对于同一个作用域中的{var a = 1;var a = 2},对变量a的声明,后者的声明会被忽略,因为之前已经声明过了,对a的赋值操作,后者还是会正常执行,2就会取代原来在内存中的1,也就是我原来理解的覆盖。),然后编译器生成引擎执行所需的代码,也就是赋值操作,引擎会问作用域是否存在a变量,引擎会在作用域中查询,如果有就把2保存进去,如果没有就继续查询(这里设计到作用域链),查完之后还没有就会抛出异常报错。
(JavaScript引擎会在代码执行前对其进行编译)
编译器生成代码后,引擎开始执行代码,例如 a = 2 这个赋值操作代码,引擎是如何去找到a 和 2的用的就是LHS和RHS查询他们两的含义是赋值操作的左侧查询和右侧查询
LHS查询可以理解为针对“目标“的查询,例如 a = 2 这个赋值操作,LHS查询是针对a这个目标进行查询,要将2赋值给a,那么需要通过LHS查询去看看a变量存不存在(在非严格模式中如果没有声明a就去赋值,引擎是会自动声明a不会报错,但是严格模式下就会报错了)RHS查询可以理解为针对“源”的查询,例如a = b ,RHS查询是要去查询b这个源,要通过RHS查询去看看b变量是什么,是个基本类型还是引用类型词法作用域:
是一种作用域的工作模式,在编译阶段的词法分析阶段,会根据代码的词法位置来生成对应的作用域