浅谈LHS和RHS

2 分钟阅读

浅谈 LHS 和 RHS

LHS 和 RHS 这两个术语听起来陌生,但它们描述的查找动作在 JS 里无处不在——每一次变量读取和赋值,背后都是其中之一在执行。理解这两个概念,能帮你真正搞懂 ReferenceError 和 TypeError 的区别。

1. 两种查找方式

JS 引擎在作用域中查找变量时,根据查找目的的不同分为两种方式:

  • LHS(Left-hand Side):查找的目标是变量的引用本身,目的是赋值——“我要往这个容器里写东西”
  • RHS(Right-hand Side):查找的目标是变量的值,目的是读取——“我要拿到这个容器里的内容”

看两个例子:

javascript
const a = 'string'

这里对 a 进行的是 LHS 查询:引擎需要找到(或创建)变量 a 这个容器,然后把 'string' 写进去。

javascript
const b = a

这一行两种查询都有:对 a 是 RHS 查询(读取它的值),对 b 是 LHS 查询(把读到的值赋给它)。

2. 查找失败时:两种错误的来源

两种查询在"找不到变量"时的行为不同,这正是两类常见报错的根源。

RHS 查询失败——在整条作用域链上都没找到这个变量,引擎抛出 ReferenceError(引用错误):

javascript
console.log(notExist) // ReferenceError: notExist is not defined

RHS 查询成功,但用了不合法的操作——变量找到了,值也拿到了,但你对这个值做了它不支持的事,抛出 TypeError(类型错误):

javascript
const a = 'string'
const b = a() // TypeError: a is not a function

a 是字符串,不能被当作函数调用。RHS 找到了 a,但"调用"这个动作对它的类型不合法。

一句话总结:ReferenceError 是"找不到",TypeError 是"找到了,但你乱来"。

3. 严格模式下的 LHS 差异

非严格模式下,LHS 查询在全局作用域也找不到变量时,会隐式创建一个全局变量——这是臭名昭著的"意外全局变量"来源:

javascript
function foo() {
  bar = 1 // 非严格模式下,bar 会被挂到全局
}
foo()
console.log(bar) // 1

严格模式下同样的代码会直接抛出 ReferenceError。这也是建议始终开启严格模式的原因之一:它把"写错变量名"这类静默错误变成了显式报错。

参考资料

相关文章
前后篇
← NEWER聊一聊京东的面试(金融组&物流组)OLDER →面试题之手写new apply call bind
评论