理解作用域(引擎,编译器,作用域)

  在JS中,引擎,编译器,作用域分别扮演以下角色:

      引擎:负责整个Js程序的编译以及执行过程。

      编译器:负责语法分析以及代码生成等。

      作用域:负责收集并维护所有声明的标示符(变量)组成的一系列查询,并实施一套严格的规则,确定当前执行的代码对这些标识符的访问权限。

  

 下面用一个小例子来表示:

     

 var a = 2;

      1.首先,遇到var a,编译器会询问当前作用域是否有一个该变量存在,如果存在,编译器则会忽略进行下一步,否则编译器会要求作用域在当前声明一个新的变量,并命名为a。

      2.接下来编译器会为引擎生成运行时所需要的代码,这些代码被用来处理 a = 2这个赋值操作,引擎运行时首先询问作用域,是否存在变量a,若存在,引擎就会直接使用该变量,否则引擎会继续向上一个作用域寻找,直到找到为止,如果在全局作用域还未找到,此时引擎会抛出一个异常。

  

 关于引擎查询:

       引擎查询有两种查询方式,分别为LHS(左查询)和RHS(非左查询)

       LHS查询是找到该变量的容器,如var a = 2; 在查询a时就需用到LHS查询。

       RHS查询可以理解为找到该变量的值,如 a = b ,在查询b时,仅需要得到它的值,并不关心他本身容器,故使用RHS查询。

 一个小例子便于理解:

      

 function foo(a){

          var a = b;

          return a+b;

       }

       var c = foo(2);

其中使用了三次LHS,分别为 var c,var a,以及foo(2)的时候把2赋值给a(隐式赋值);

      使用了四次RHS,分别为foo(2), = b, return a + b(a,b)各一次。 

   

  关于为什么要区分LHSRHS是很重要呢?

  因为异常

  在变量还未声明的情况下(即在任何作用域都找不到该变量),这两种查询的方式是不同的。

  LHS

       LHS在非严格模式下,找不到该变量时,它会直接声明一个该变量,如a = b,中的a会被声明。但如果在严格模式下,则会抛出一个ReferenceError.

  RHS:

       RHS找不到时会直接抛出一个ReferenceError.

       ReferenceError是同作用域判定失败有关,而TypeError则是代表作用域判别成功,但是对结果的操作属于非法,比如试图对一个非函数的值进行函数调用。

  

原文地址:https://www.cnblogs.com/Darlietoothpaste/p/6344126.html