var number = 1;
当你看到这段代码的时候,你可能简单的认为是为变量$\color{red}{number赋值为1}$。事实上,这里是分为两个阶段处理,$\color{red}{一个是编译器编译处理,一个是引擎运行处理}$。是由编译器和引擎协助工作。
- 首先将分词/词法分析这段代码分解为词法单元。
- 然后解析语法分析,生成一个抽象语法树-AST。
- 最后进行代码生成。
引擎:负责整个JavaScript的编译和执行过程。编译器:负责JavaScript的语法分析和代码生成。
一、编译器生成代码时做了什么?
- 遇见var number,编译器会询问作用域中是够已经有一个名称为number的变量存在于当前作用域中,如果存在,会忽略当前声明。如果不存在就是在当前作用域声明一个变量number。这这个阶段是进行变量提升的一个过程【JavaScript变量提升运行机制】。
- 然后编译器会生成引擎运行时需要的代码。生成代码用来处理赋值的操作。
- 引擎运行时,首先会询问当前作用域是否有一个变量number,如果有直接使用这个变量。如果没有,引擎会继续查询该变量。直至最外层(全局作用域)。如果引擎找到变量number,就将1这个值赋给number,反之引擎会抛出一个异常。
详情完整的JavaScript的代码运行机制,请看这里。
$\color{red}{引擎执行怎么样的查找,}$$color{red}{在我们的例子中,引擎会为变量number进行LHS查询,与之相对的就是RHS查询。}$
二、LHS查询&RHS查询
正常的猜想"L"、"R"就是左边和右边,赋值操作的左边和右边,根据这个猜想,当变量出现在赋值操作的左侧是进行LHS查询,当再出现赋值操作的右边进行RHS查询。
console.log(number);
这段代码对number的引用是一个RHS查询,这里number没有赋值任何值,(可能你会说,兄弟你这一行代码会报错,没有声明变量number,不好意思,打扰了举着栗子。)
number = 1;
这里对number是一个LHS查询,引擎并不关心当前赋值的值是什么,只是想为 = 1 找到一个目标。
LHS查询和RHS查询的含义是"赋值操作的左侧和右侧",并不一定是意味着是" = 赋值操作符的左侧和右侧"。
赋值操作还有其他几种形式,因此在概念上最好将其理解为"赋值操作的目标是谁(LHS)"以及"谁是赋值操作的源头(RHS)"。
----------摘抄《你不知道JavaScript上卷》
function func(number) {
console.log(number);
}
func(1);
上面的代码既有LHR查询也有RHS查询,我们一起来分析一下。
- 运行func()函数时,对func进行了RHS查询,查询func操作的源头。
- 隐藏的声明number = 1,这里是将1传给函数func,1被分配赋值给number,查询操作的目标是谁,进行一次LHS查询。
- console.log需要一个查询才能执行,先会对console,进行一个RHS查询,并检查console对象是否有一个log的方法。
- 然后会对number进行一个RHS查询。
- 最后在console.log()输出number的值。
看似简单的一段代码执行,其中进行了很多的LHR查询和RHS查询,这就是引擎需要重复操作的动作。
三、小测试
function foo(a) {
var b = a;
console.log(a);
console.log(b);
return a + b;
}
var c = foo(2);
- 找出其中所有LHS查询。
- 找出其中所有RHS查询。
参考【《你不知道JavaScript上卷》】
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。