前言:JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行。代码是无法直接运行的,需要通过JavaScript编译器对其进行编译,只有编译后的代码才可以被识别,然后通过JavaScript引擎执行代码逻辑。
举例:
var a = 2;
一、编译
1.分词:
分词的目的是将这些代码分解为一个个有意义的代码块,这些代码块称为词法单元。
var a = 2; // 将被分解为'var、a、=、2、;'这些词法单元组成了一个词法单元流数组
// 词法分析后的结果
[
"var" : "keyword",
"a" : "identifier",
"=" : "assignment",
"2" : "integer",
";" : "eos" (end of statement)
]
2.解析:
对刚才分词得到的一个个代码块进行解析,生产一个抽象的语法树;
(抽象语法树(Abstract Syntax Tree, AST)把词法单元流数组转换成一个由元素逐级嵌套所组成的代表程序语法结构的树。)
Program body[1]:{ // 代表代码是一个程序
Variable Declaration:{ // 变量声明
declarations[1]:{ // 声明数组
Variable Declaration:{ // 变量声明
id:{ // 变量名
Identifier:{ // 标识符
name: a
}
},
init: { // 初始化操作
Literal: {
value: 10,
raw: 10
}
}
}
},
kind:var // 代表种类
}
}
3.代码生成:
将AST转换为可执行代码的过程被称为代码生成。
JavaScript引擎会把在第二步中生成的抽象语法树进行转换,转换成可执行的 代码(机器指令),用来创建一个叫做a的变量(包括分配内存等),并将值 2储存在a中。
二、执行
1.执行原理:
1.1 引擎运行时会首先查询作用域,在当当前的作用域集合中是否存在一个叫作a的变量。
如果是,引擎就会使用这个变量;
如果否,引擎会继续查找该变量,就会向上级做用域继续查找目标标识符,这样每次上升一级做用域,最后抵 达全局做用域(顶层),不管找到或没找到都将中止。
1.2 如果引擎最终找到了变量a,就会将2赋值给它,否则引擎会抛出一个异常。
1.3 变量查询的两种方式:LHS和RHS
-
RHS查询与简单地查找某个变量的值别无二致,而LHS查询则是试图找到变量的容器自己,从而能够对其赋值。从这个角度说,RHS并非真正意义上的“赋值操做的右侧”,更准确地说是“非左侧”函数
-
LHS和RHS的含义是“赋值操做的左侧或右侧”并不必定意味着就是“=赋值操做符的左侧或右侧”。赋值操做还有其余几种形式,所以在概念上最好将其理解为“赋值操做的目标是谁(LHS)”以及“谁是赋值操做的源头(RHS)”。
注意点
-
LHS和RHS查询都会在当前执行做用域中开始,若是有须要(也就是说它们没有找到所需的标识符),就会向上级做用域继续查找目标标识符,这样每次上升一级做用域(一层楼),最后抵达全局做用域(顶层),不管找到或没找到都将中止。不成功的RHS引用会致使抛出ReferenceError异常。不成功的LHS引用会致使自动隐式地建立一个全局变量(非严格模式下)
-
查找只会查找一级标识符,好比a、b和c。若是代码中引用了foo.bar.baz,词法做用域查找只会试图查找foo标识符,找到这个变量后,对象属性访问规则会分别接管对bar和baz属性的访问。
-
若是RHS查询找到了一个变量,可是你尝试对这个变量的值进行不合理的操做,好比试图对一个非函数类型的值进行函数调用,或者引用null或undefined类型的值中的属性,那么引擎会抛出另一种类型的异常,叫做TypeError。
a = 2;
console.log(a); // 2 自动建立一个全局变量
console.log(a) // undefined console.log语句执行的时候,var a=function尚未被执行,但 是全部代码已被编译,所以变量a已经被放置在内存中
var a = function () {
document.write("hellow world!")
}
console.log(apple); // ReferenceError: apple is not defined
var b;
console.log(b); // undefined
a (); // TypeError: a is not a function 通过编译变量a被储存,但没有赋值为函 数,还不是函数类型所以调用函数a是为对变量进行不合理的操作
var a = function () {
document.write("hellow world!")
}
var b;
b = a;
console.log(b); // ReferenceError: a is not defined