你不知道的JS系列(2)- 引擎怎么查找变量

对代码进行处理的三个角色
引擎:从头到尾负责整个 JavaScript 程序的编译和执行过程
编译器:负责语法分析及代码生成等
作用域:负责收集并维护所有变量的查询

 

var a = 2;
编译器首先会将这段程序分解成词法单元,然后将词法单元流解析成一个树结构。然后将树结构转换成可执行代码,也就是计算机懂的指令。为一个变量分配内存,将其命名为 a,然后将值 2 保存进这个变量。这符合编译原理

 

然而并不完全正确

 

事实上编译器会进行如下处理
1、在词法分析中,遇到 var a,编译器会询问当前作用域是否有该变量。是,忽略该变量继续编译。否,要求作用域声明一个新的变量
2、在生成代码中,编译器对 a = 2 进行赋值操作。首先询问作用域,在当前作用域是否存在该变量。是,使用该变量。否,引擎继续查找该变量

如果引擎找到了 a ,就将 2 赋值给它。否则抛出异常

变量赋值操作会执行两个动作,一个是编译器在当前作用域声明该变量,然后引擎在作用域中查找该变量,进行赋值

 

查找的过程由作用域进行协助,但是引擎执行怎么样的查找,会影响最终的查找结果。引擎会为变量 a 进行 LHS 查询。另外一个查找的类型叫做 RHS 。它们代表赋值操作的左侧和右侧。更准确的说,LHS 查询是试图找到变量的容器本身。

 

LHS 和 RHS 的含义是 “赋值操作的左侧或右侧”,并不一定意味着就是 “ = 赋值操作符的左侧或右侧”。赋值操作还有其他几种形式,因此在概念上最好将其理解为 “赋值操作的目标是谁(LHS)” 以及 “谁是赋值操作的源头(RHS)”。

 

比如
function foo(a) {
  console.log(a) //2
}
foo(2);
对 foo 进行 RHS 引用。对 a 进行 LHS 引用。对 console 进行 RHS 引用

 

function foo(a){
  var b = a;
  return a + b;
}
var c = foo(2);
这里 LHS 有 3 处,RHS 有 4 处
 
这里每一次查找,都需要跟作用域配合一次
 

 

posted @ 2020-02-12 09:36  wzndkj  阅读(304)  评论(0编辑  收藏  举报