为了进一步理解,我们需要多介绍一点编译器的术语。
编译器在编译过程的第二步中生成了代码,引擎执行它时,会通过查找变量 a 来判断它是
否已声明过。查找的过程由作用域进行协助,但是引擎执行怎样的查找,会影响最终的查
找结果。
在我们的例子中,引擎会为变量 a 进行 LHS 查询。另外一个查找的类型叫作 RHS。
我打赌你一定能猜到“L”和“R”的含义,它们分别代表左侧和右侧。
什么东西的左侧和右侧?是一个赋值操作的左侧和右侧。
换句话说,当变量出现在赋值操作的左侧时进行 LHS 查询,出现在右侧时进行 RHS 查询。
讲得更准确一点,RHS 查询与简单地查找某个变量的值别无二致,而 LHS 查询则是试图
找到变量的容器本身,从而可以对其赋值。从这个角度说,RHS 并不是真正意义上的“赋
值操作的右侧”,更准确地说是“非左侧”。
你可以将 RHS 理解成 retrieve his source value(取到它的源值),这意味着“得到某某的
值”。
LHS(Left-hand Side):left是指“=”号的左边,意思是要给查询得到的这个变量赋值,比如要吧1付给a变量,要先查询a是否存在,这时候用的就是LHS查询
RHS(Right-hand Side):right指的是“=”号右边,意思是要获取某个变量的值,比如打印a变量,console.log(a);js引擎要去查询这个变量是否存在,得到变量只想的值,这个时候用的就是RHS查询
LHS查询比较松散,如果查询不到,就会创建一个全局的,不会抛出异常
RHS查询比较严格,如果查询不到的话就会抛出异常,因为你要获取某个变量指向的值,可是根本就没有那个变量,这个时候已经超出它的能力范围,所以只能抛出异常
其实这也是符合js的松散的本性,好比你要给钱某个人,找不到那个人,我就用它的名义领了,毕竟这不吃亏,这是LHS,但是如果你是追债,那必须要找到欠你的钱那个人,我不可能替你还钱的,这就是RHS,如果找不到只能报警,抛出异常
看到这里就能理解为什么使用未定义的变量有时候报错有事不报错了
如果是访问对象的属性就不存在LHS查询和RHS查询了,找不到就返回undefined