第一章(关于引擎与编译器的互动行为以及嵌套作用域的过程理解)
首先我先上一个demo来解释作用域的问题,在这段解释的过程中会详细讲解一些js引擎的行为。
在上demo之前,需要先让大家了解的是编译器与引擎的关系
编译器:负责的是语法分析与代码的生成,也就是说作用域中的变量与语法的声明与代码构成都由编译器负责;
引擎:贯通整个js的执行过程,通俗的来说就是编译器是部门主管,而引擎是CEO;
上demo1
Function Query(a){
Var c=a+2;
Return c;
}
Query(5);//7
Console.log(c);//referenceError 报错c未定义
接下来为大家解释这个过程,其中涉及到数次的LHS与RHS查询操作:
解释这个前提是明白LHS与RHS的意思,LHS代表左侧赋值查询,RHS代表右侧赋值查询,简单的来说:
Var a=5; //其中各进行了一次LHS查询与RHS查询;
其中a=... //LHS查询
...5 //RHS查询
引擎在var a=5;这个过程中的行为步骤是:
①编译器声明变量a;
②请求编译器在全局作用域中左侧查询(LHS)变量a,在严格模式下,若不存在则报错ReferenceError:a is not define;
③右侧查询(RHS)变量a的值5并对a进行赋值;在非严格模式下,左侧查询失败会在全局自动创建变量a,若此时右侧查询失败,则也会返错ReferenceError:a is not define;
接下来我们可以开始解释demo1的为什么报错的过程了:
Function Query(a){
Var c=a+2; //声明变量c LHS查询(2次) RHS查询(2次)
Return c; //RHS查询(1次) RHS查询->7
}
Query(5);//7 //此为RHS查询(1次) RHS查询->7(没有变量接住,执行 完成后便会被内存释放)
Console.log(c);//referenceError 报错c未定义 RHS查询c的值
*但我们通过上面的引擎行为解释过,引擎是先进行LHS左侧查询的变量c的,此时引擎会先去询问编译器是否有全局变量c,因为引擎是向上冒泡的故在全局引用时不会向下去查询同名局部变量,而只有局部变量向上查询需要的同名全局变量!
此时在非严格模式下编译器中没有全局变量c,则会自动创建一个变量c,然后引擎在console.log时再次进行右侧查询RHS未查询到值,则返回了ReferenceError。
与书中对ReferenceError报错的解释相同,以下为书中原文:
原文:不成功的RHS引用会导致抛出ReferenceError异常。不成功的LHS引用会导致自动隐式地创建一个全局变量(非严格模式下),该变量使用LHS引用的目标作为标识符,或者抛出ReferenceError异常(严格模式下)。
前文还提到:如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常。
正确方式
Function Query(a){
Var c=a+2; //声明局部变量c LHS查询(2次) RHS查询(2次)
Return c; //将局部变量c的值return到全局
//其中RHS查询(1次) RHS查询->7
}
Var c=Query(5); //RHS(1) LHS(1) LHS->c RHS->Query(5)->7
Console.log(c); //7 RHS(1);
仅利用这个例子来说明自己对这个章节的一些理解,如果其中有错误或漏说的地方还请大家指点一二,谢谢~