JavaScript程序中的一段源代码在执行之前会经历三个步骤,统称为编译
-
<李>分词/词法分析李>
<李>解析/语法分析李>
<李>代码生成李>
<强>先看原书对一个赋值操作的拆解说明:强>
变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值。- - - - - -《你不知道的JavaScript(上卷)》第七页
而要讲的lh和RHS就是上面说的对变量的两种查找操作,查找的过程是由作用域(词法作用域)进行协助,在编译的第二步中执行。
<强> lh和RHS 强>
-
<李>字面意思其实是<代码>左手边代码>和<代码>右手边> 代码即左手边和右手边李>
<李>一般可以理解为<代码>赋值操作的左侧和右侧代码> 李>
先看个例子一
console.log(一个);
这里对一个是一个园艺学会引用,因为一个并没有赋予任何值,目的是为了取到一个的值并打印出来。
=2;
这里对一个是一个lh引用,因为实际上我们不关心当前的值是什么,只是想要把一个赋值为2。
再看例子二
函数foo () { console.log(一个);//2 }foo (2);
-
<李>最后一行foo(. .)函数的调用需要对foo进行RHS引用,意味着是取到foo的值,并且(. .)意味着foo需要被执行,因此它最好是一个函数类型的值
李> <李>其中有一个容易被忽略的隐式赋值操作=2,它发生在2被当做实参传入foo中时。即实参2传给了形参,需要一个韩查询李> <李>控制台那一行还有对一个的一次RHS引用(或者叫查询),同时console.log(. .)本身也需要一个RHS引用,即对控制台对象进行RHS查询,并且检查得到的值中是否有一个叫做日志的方法。李> <李>书中有一段引擎和作用域的对话,有助于很好的理解例子二,看到YDKJS github李>
小测验
函数foo () { var b=一个; 返回一个+ b; } var c=foo (2);
试试找出其中的3处韩查询,4处RHS查询
答案:
<代码> lh查询:
代码>
c=. .;
=2(隐式变量分配)
b=. .
<代码> RHS查询代码>
foo (2 . .
=,
一个. .
.. b
<强>小结强>
参考原书中文版P12,英文版见github
-
<李>作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。李>
<李>如果查找的目的是对变量进行赋值,就会使用韩查询,如果目的是获取变量的值,就会用RHS查询。李>
<李>赋值操作会导致韩查询。=操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作,即都会导致韩查询。李>
<李> JavaScript引擎首先会在代码执行前对其进行编译,在这个过程中,像var=2这样的声明会被分解成两个独立的步骤:李>
<李>首先,var在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。李>
<李>接下来,=2会查询(lh查询)变量一个并对其进行赋值。李>
<李> lh和RHS查询都会在当前执行作用域中开始,如果有需要(也就是说它们没有找到所需的标识符),就会向上级作用域继续查找目标标识符,这样每次上升一级作用域,最后到达全局作用域,无论找到或没找到都将停止。李>
<李>不成功的RHS引用会导致抛出ReferenceError异常。不成功的lh引用会导致自动隐式地创建一个全局变量(非严格模式下),该变量使用lh引用的目标作为标识符,或者抛出ReferenceError异常(严格模式下)。李>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。