var a=1 居然蕴含着这么多知识?!

3 阅读3分钟

LHS(Left-Hand Side)RHS(Right-Hand Side) 的角度,结合 JavaScript 引擎、编译器和作用域系统 来完整解析 var a = 1; 这一行代码背后发生了什么。


🧠 核心流程回顾

在 JavaScript 中,任何变量的使用都涉及两个基本操作:

类型含义示例
LHS 查询找到变量的位置,以便为其赋值a = 1
RHS 查询找到变量的值,用于读取或使用console.log(a)

✅ 分析 var a = 1;

我们将这行代码拆分为几个阶段,并分别分析 LHS 和 RHS 的行为。

🔍 第一步:编译阶段(Compiler)

var a = 1;

编译器做了什么?

  1. 识别变量声明 var a

    • 在当前作用域中注册一个变量名 a
    • 这个过程叫“变量提升”(Hoisting),只声明不赋值。
    • 目的是告诉引擎:“这个变量我提前声明了,你执行的时候不要报错。”
  2. 绑定赋值操作

    • 编译器知道等一下要执行 a = 1,也就是一次 LHS 查询(给变量 a 赋值)。

编译器总结:

  • 注册变量 a 到当前作用域。
  • 准备好后续执行时对 a 的 LHS 操作。

⚙️ 第二步:执行阶段(Engine)

当 JS 引擎开始执行这一行代码时:

var a = 1;

引擎会做两件事:

1. LHS 查询:找到变量 a 的位置

  • 引擎问作用域:“我在当前作用域能给 a 赋值吗?”
  • 如果可以,则允许赋值。

2. 将值 1 赋给 a

  • 实际上是把内存中的值写入变量 a 的存储空间。

⚠️ 注意:这里没有 RHS 查询,因为右边的 1 是字面量,不是变量。


📌 总结:var a = 1; 全过程详解

阶段行为是否有 LHS/RHS
编译阶段编译器注册变量 a 到当前作用域
编译阶段编译器准备赋值动作 a = 1✅ LHS(预处理)
执行阶段引擎查找 a 的位置(LHS 查询)✅ LHS
执行阶段引擎将值 1 写入 a

🧩 举个更复杂的例子:带 RHS 查询

var b = a;

这段代码中包含:

编译阶段:

  • 声明变量 b
  • 准备执行 b = a

执行阶段:

  • LHS 查询 b:找到变量 b 的位置以赋值。
  • RHS 查询 a:获取变量 a 的值,然后赋给 b

🎯 LHS vs RHS 精准定义

类型触发条件行为报错情况
LHS给变量赋值查找变量的位置(用于写入)找不到且非严格模式 → 自动创建全局变量;严格模式下报错
RHS使用变量的值查找变量的值(用于读取)找不到 → ReferenceError

🧱 结合作用域机制

  • var a = 1; 中的 a 会被注册在:

    • 当前函数作用域(如果在函数内)
    • 或者全局作用域(如果不在任何函数中)
  • 如果你在另一个作用域中访问 a,引擎会沿着作用域链向上查找。


📝 最终总结图解

源码:var a = 1;

[编译阶段]
  └── 编译器识别 var a 并提升
  └── 记录赋值操作 a = 1 (准备 LHS[执行阶段]
  └── Engine: LHS 查询 a → 找到作用域中的 a
  └── 将 1 赋值给 a
  
  var a=b
  
  编译器识别var a 并提升 ->  通过RSH 查询 a ->找到作用域中的a -> 通过LHS 查询 将 a的值赋值给 b