题目 02 / 14

当形参与局部 var 变量同名时会发生什么?

知识点: 词法作用域

与已存在的形参同名的 var 声明不会创建新绑定,而是复用形参的绑定。

使用执行可视化器解题在下方逐步观察每个绑定、函数调用和控制台输出。

预测输出结果

预测输出结果。fn 内的 var a 会创建第二个绑定,还是只是重新赋值形参 a?

var a = 10;
function fn(a) {
    console.log(a);
    var a = 20;
    console.log(a);
}
fn(5);
查看答案与完整解析

正确输出

5
20

为什么会这样

当 fn(5) 执行时,形参 a 在函数体运行前就已经在函数的环境中绑定为 5。

声明实例化处理函数体内的 var a 时,由于 a 已经作为形参声明过,提升过程不会再创建第二个绑定,也不会把它重置为 undefined —— 复用的是形参的绑定,因此第一次 console.log(a) 输出 5。

接下来的 var a = 20 给这同一个绑定赋值为 20,所以第二次 console.log(a) 输出 20。

这道题考察什么

  • 形参绑定
  • var 与形参共用同一个绑定
  • 不会重置为 undefined

运行环境前提

这一行为由函数的声明实例化规则决定,在任意标准 JavaScript 引擎的脚本或模块代码中都成立。

规范参考

JavaScript 代码编辑器支持直接编辑或粘贴自定义代码
第 0 步 / 共 0 步
单步Space播放
按 → 单步 或 Space 自动播放
阶段 1: 编译预解析(变量提升与内存分配)
阶段 2: 代码执行(逐行赋值与调用求值)
单步执行原理解析

按键盘右方向键 “→” 进行单步调试,或按空格键 “Space” / 点击 “▶ 自动播放” 进行连续执行。

作用域链 (Scope Chain)
词法作用域链: 当前 AO → 外部 [[Scope]] → 全局 (GO)
暂无激活的作用域链
调用栈 (CALL STACK)执行上下文栈 (后进先出 LIFO)
后进先出 (LIFO) 栈帧
全局执行上下文 (GEC)
▶ 活动栈帧
堆内存空间 (HEAP & MEMORY SPACE)已分配对象 (GO, AO, FunctionObjects, ER)
ECMAScript 堆内存区
内存中暂无分配对象
控制台输出 (Console)
console.log(...) Stream
暂无输出产生