为什么你的 JS 代码有时崩溃有时侥幸运行?LHS/RHS 的“潜规则”全解析

JavaScript中的LHS与RHS查询:为什么有的代码会报错,有的却不会?

在 JavaScript 中,变量的查找机制分为 LHS(Left-Hand Side)查询RHS(Right-Hand Side)查询。这两种查询方式在作用域中的行为不同,直接影响了代码是否会抛出错误。本文将通过两个示例代码,详细解释它们的区别。


示例1:RHS查找失败导致报错

javascript 复制代码
function foo(a) {
  console.log(a + b); // RHS查找b失败,报错!
  b = a;
}
foo(2); // 报错:ReferenceError: b is not defined

在这段代码中,函数 foo 试图在 console.log(a + b) 中计算 a + b 的值。此时,引擎会对变量 b 进行 RHS查询 (即查找 b 的值)。然而,在 foo 的作用域内,b 尚未被定义,且全局作用域中也没有 b 的声明。此时 RHS 查找失败,引擎直接抛出 ReferenceError 异常,代码终止执行。

关键点

  • RHS 查询的目的是获取变量的值,失败时会抛出错误。
  • 代码中 b = a 位于 console.log 之后,因此还未执行到这一步,b 未被赋值。

示例2:LHS隐式创建全局变量

javascript 复制代码
function foo() {
  b = 2; // LHS查找b失败,自动创建全局变量!
}
foo();
console.log(b); // 输出2(全局变量生效)

在这段代码中,函数 foo 内部对 b 进行了赋值操作 b = 2。引擎此时会进行 LHS查询 ,尝试找到变量 b 的位置以便赋值。由于当前作用域(foo 内部)和上层作用域(全局)中均未声明 b,在非严格模式下,引擎会隐式地在全局作用域中创建一个全局变量 b 并赋值为 2。因此后续的 console.log(b) 可以正常输出。

关键点

  • LHS 查询的目的是找到变量容器本身(赋值的目标位置),失败时在非严格模式下会隐式创建全局变量。
  • 严格模式("use strict")下,LHS 失败也会抛出 ReferenceError

LHS 与 RHS 的核心区别

  1. 目的不同

    • RHS :查找变量的值(如 console.log(a) 中的 a)。
    • LHS :查找变量容器本身(如 a = 3 中的 a),以便赋值。
  2. 失败时的行为

    • RHS 失败 :直接抛出 ReferenceError
    • LHS 失败(非严格模式):自动在全局作用域创建变量。
    • LHS 失败 (严格模式):同样抛出 ReferenceError
  3. 作用域链的查找机制

    • 两种查询都会沿着作用域链逐级向上查找,直到全局作用域。
    • RHS 失败时立即终止;LHS 失败时(非严格模式)在全局作用域"兜底"。

严格模式下的差异

在严格模式("use strict")中,LHS 的行为会发生变化:

javascript 复制代码
"use strict";
function foo() {
  b = 2; // LHS失败,严格模式下报错!
}
foo(); // ReferenceError: b is not defined

严格模式禁止自动创建全局变量,因此 LHS 查找失败时也会抛出错误,与 RHS 行为一致。


总结

  • RHS 失败必报错:因为引擎需要获取变量的值,找不到时无法继续执行。
  • LHS 失败可能隐式创建变量(仅在非严格模式):这一特性可能导致意外的全局变量污染,需谨慎使用。
  • 推荐使用严格模式:避免隐式全局变量,提升代码安全性。

理解 LHS 和 RHS 的机制,能帮助我们更好地调试作用域相关的问题,并写出更健壮的代码。

相关推荐
睡美人的小仙女1274 小时前
在 Vue 前端(Vue2/Vue3 通用)载入 JSON 格式的动图
前端·javascript·vue.js
大宝贱5 小时前
H5小游戏-超级马里奥
javascript·css·html·h5游戏·超级马里奥
weixin_490354347 小时前
Vue设计与实现
前端·javascript·vue.js
GISer_Jing8 小时前
React过渡更新:优化渲染性能的秘密
javascript·react.js·ecmascript
烛阴9 小时前
带你用TS彻底搞懂ECS架构模式
前端·javascript·typescript
wayhome在哪9 小时前
3 分钟上手!用 WebAssembly 优化前端图片处理性能(附完整代码)
javascript·性能优化·webassembly
web前端12310 小时前
# 多行文本溢出实现方法
前端·javascript
人间观察员10 小时前
如何在 Vue 项目的 template 中使用 JSX
前端·javascript·vue.js
EndingCoder10 小时前
安装与环境搭建:准备你的 Electron 开发环境
前端·javascript·electron·前端框架
Lucky_Turtle10 小时前
【electron】一、安装,打包配置
javascript·arcgis·electron