JavaScript Hoisting内存创建阶段提升规则与代码形态疑问
你梳理的提升后结构不正确,问题出在你把var foo = 3的赋值逻辑也直接删掉了,实际上只有var foo的声明部分会被忽略,赋值操作会保留在原位置等待执行。
先明确JS提升的核心规则:
- 提升仅处理「声明」逻辑,所有赋值操作都会留在原代码的位置,在执行阶段按顺序运行
- 同一作用域内,函数声明的提升优先级高于var变量声明:如果同名标识符已经被函数声明注册,后续的同名var声明会直接被跳过,不会覆盖已有的标识符绑定
- 同一作用域内的同名函数声明,后出现的会覆盖先出现的绑定
你给出的代码完整处理流程
1. 内存创建(提升)阶段处理逻辑
按代码顺序扫描所有声明:
- 扫描到第一个
function foo()声明,在作用域中注册标识符foo,值为返回1的函数 - 扫描到第二个
function foo()声明,覆盖已有的foo绑定,此时foo的值为返回2的函数 - 扫描到
var foo声明,发现foo已经在作用域中存在,该声明直接被忽略,不做任何处理
2. 执行阶段逻辑
按原代码的顺序执行剩下的逻辑,已经处理过的声明不会重复执行:
- 执行
console.log(foo),此时foo还是提升阶段绑定的返回2的函数,因此输出对应结果 - 跳过两个已经处理过的函数声明
- 执行
var foo = 3剩下的赋值逻辑foo = 3,此时foo的值才会被修改为3,但这一步在打印操作之后,不会影响打印结果
正确的等效提升后代码
// 提升阶段完成的声明处理 function foo() { return 1; } // 后声明的同名函数覆盖前一个绑定 function foo() { return 2; } // var foo 的声明部分因重复被忽略,仅剩余赋值操作留在原位置 // 执行阶段按原顺序运行 console.log(foo); // 输出为:foo() { return 2; } // 函数声明已在提升阶段处理,执行时无实际操作 foo = 3;
关于你的疑问:你认为“这段代码中并没有重复的var声明”是对的,但这里的“重复声明”指的是标识符foo已经通过函数声明完成了注册,不属于var声明之间的重复,只要是同一作用域内同名的声明,函数声明优先级更高,var的声明就会被跳过,仅保留赋值逻辑。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

