一、编译阶段
当代码var a = 1被解析时,编译器会执行以下关键步骤:
- 声明检查
编译器向当前作用域查询是否已存在同名变量声明:
- 存在 → 忽略当前声明(变量提升机制)
- 不存在 → 在作用域中创建新变量标识符
a
- 变量提升特性
使用var声明的变量会提升至作用域顶部,等价于:
var a; // 声明提升
a = 1; // 赋值保留原位
二、执行阶段
当引擎执行赋值操作时,触发两种查询机制:
LHS(Left-Hand Side)查询
- 目标定位:赋值操作的目标是谁
- 执行场景:赋值操作左侧(
a = 1)、函数参数传递 - 失败处理:
- 非严格模式:自动创建全局变量
- 严格模式:抛出ReferenceError
RHS(Right-Hand Side)查询
- 值获取:谁是赋值操作的源头
- 执行场景:变量引用(
console.log(a))、函数调用 - 失败处理:直接抛出ReferenceError
function foo(a) { // LHS查询(参数赋值a=2)
console.log(a); // RHS查询(获取a的值)
}
foo(2); // RHS查询(查找foo函数)
三、作用域嵌套机制
作用域链工作原理
- 引擎从当前作用域开始查找
- 逐级向外层作用域扩展
- 最终到达全局作用域
- 查找终止条件:
- 找到目标变量 → 返回对应值
- 到达全局仍未找到 → 根据模式处理
典型示例
function outer() {
var b = 20;
function inner() {
console.log(b); // 当前作用域 → outer作用域 → 找到b=20
}
inner();
}
outer();
四、异常处理机制
异常场景分析
- RHS失败:
console.log(undefVar); // ReferenceError
- 无效操作:
var foo = 123;
foo(); // TypeError(数字不可调用)
- 严格模式保护:
"use strict";
undefVar = 10; // ReferenceError
五、特殊处理机制
非严格模式特性
function test() {
// 隐式全局变量创建
unexpectedVar = 100;
}
test();
console.log(unexpectedVar); // 输出100(污染全局空间)