You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数与变量提升的意外结果:为何代码输出为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:56:18