又是一年临近年末了,年末制定下了许多计划,正在一点一点实现,最近在开始读《你不知道的Javascript》了,也会慢慢把读书笔记经过博客的形式输出出来,让本身印象更深入,今天就来聊聊JS中的var a = 2;
这行代码发生了什么?编程
对于编程语言来讲都会有一个编译的过程,一段代码在执行前大多都会经历下面几个步骤:(具体的细节会根据语言特性而异)数组
这个过程会将由字符组成的字符串分解成(对编程语言来讲)有意义的代码块,这些代 码块被称为词法单元(token)。例如,考虑程序 var a = 2;。这段程序一般会被分解成 为下面这些词法单元:var、a、=、2 、;。bash
这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的表明了程序语法 结构的树。这个树被称为“抽象语法树”(Abstract Syntax Tree,AST)。编程语言
将 AST 转换为可执行代码的过程称被称为代码生成。这个过程与语言、目标平台等息 息相关。 抛开具体细节,简单来讲就是有某种方法能够将 var a = 2; 的 AST 转化为一组机器指 令,用来建立一个叫做 a 的变量(包括分配内存等),并将一个值储存在 a 中。函数
从头至尾负责整个 JavaScript 程序的编译及执行过程。ui
负责语法分析及代码生成等spa
负责收集并维护由全部声明的标识符(变量)组成的一系列查询,并实施一套很是严格的规则,肯定当前执行的代码对这些标识符的访问权限。code
咱们在了解了这些编译中的基本概念后,咱们在来仔细看看var a = 2;
这行代码发生了什么;token
var a
,编译器会询问做用域是否已经有一个该名称的变量存在于同一个做用域的集合中。若是是,编译器会忽略该声明,继续进行编译;不然它会要求做用域在当前做用域的集合中声明一个新的变量,并命名为 a。(变量声明阶段)总结:变量的赋值操做会执行两个动做,首先编译器会在当前做用域中声明一个变量(若是以前没有声明过),而后在运行时引擎会在做用域中查找该变量,若是可以找到就会对它赋值。ip
咱们知道了var a = 2;js的执行过程了,那么若是是var a = b;呢? 那么这个过程对于b来讲咱们如何查到变量b的值呢;
编译器查找变量有两种类型,一直是LHS,一种是RHS,举个例子:
a = 2
复制代码
这个例子就是LHS查询,当编译器去查找a变量的时候,实际上是为了找到a变量的容器,去给a赋值,因此LHS查询实际上是查询变量的容器
console.log(a)
复制代码
这个例子中的其实就是RHS查询,当编译器去查找a变量的时候,其实目的是找到a变量的值而不是他的容器,所以RHS查询实际上是查询变量的值
ok,咱们知道了以后咱们来尝试一下一个进阶例子。
function foo(a) { // 隐式的进行参数赋值 将a = 2; 进行LHS查询 查询到a容器 并进行赋值
var b = a; // RHS进行查询 查询到a变量的值 而后 LHS查询 查询到b容器并进行赋值
return a + b;// RHS进行查询 查询到a和b变量的值
}
var c = foo( 2 ); // 编译器先RHS查找foo变量 而后进入到foo函数体 函数执行完成后,RHS查询查询变量c的容器并进行赋值
复制代码
注:若是RHS查到了一个变量,可是这个变量的类型和咱们将要进行的操做不一样时,好比试图对一个非函数类型的值进行函数调用,那么就会抛出TypeError的错误