函数与变量提升的意外结果:为何代码输出为1而非报错?
为什么函数提升后同名变量声明不会覆盖函数?
这问题问得特别好,刚好说到了JS提升机制里最容易踩坑的细节!
你之所以有困惑,是因为没搞清楚函数声明和变量声明的提升优先级,以及JS处理重复声明的规则。咱们一步步拆解:
1. 提升的优先级:函数 > 变量
JS在解析代码时,会先把所有的函数声明和变量声明提升到当前作用域的顶部,但函数声明的提升优先级是高于变量声明的。也就是说,当同一个标识符既有函数声明又有变量声明时,函数声明会先被提升,之后的变量声明会被直接忽略——因为JS不允许重复声明同一个变量(但后续的赋值操作是完全合法的)。
2. 你的代码到底发生了什么?
原代码的提升过程其实是这样的:
// 第一步:优先提升函数声明,此时foo指向这个函数 function foo() { console.log( 1 ); } // 第二步:提升变量声明var foo,但因为foo已经被函数声明定义过了,这一行相当于无效操作,直接被忽略 // var foo; (这行代码不会产生任何影响) // 然后执行原代码里的执行逻辑 foo(); // 调用的是上面的函数,自然输出1 foo = function() { console.log( 2 ); }; // 这是赋值操作,会把foo的指向改成新函数,但这一步在调用之后,所以不影响之前的输出
你之前的误区在于以为var foo会把foo重置为undefined,但实际上单纯的变量声明(没有赋值)不会覆盖已经存在的函数声明。只有当你给变量赋值的时候,才会改变foo的指向。
举个反例加深理解
如果把代码改成这样:
foo(); // 猜猜输出什么? var foo = function() { console.log( 2 ); }; function foo() { console.log( 1 ); }
提升后的代码是:
function foo() { console.log( 1 ); } var foo; // 忽略 foo(); // 输出1 foo = function() { console.log( 2 ); };
还是输出1,因为赋值操作在调用之后。但如果把赋值放到调用之前:
var foo = function() { console.log( 2 ); }; foo(); // 输出2 function foo() { console.log( 1 ); }
提升后:
function foo() { console.log( 1 ); } var foo; // 忽略 foo = function() { console.log( 2 ); }; // 赋值覆盖了函数 foo(); // 输出2
这样是不是就清晰多了?
内容的提问来源于stack exchange,提问作者BoSsYyY
相关产品推荐
相关产品推荐

