函数声明提升优先于变量提升,会完整提升函数体至作用域顶部,而函数表达式仅变量名被提升、值为undefined或处于tdz;同名时函数声明覆盖变量声明,块级函数声明存在跨浏览器不一致问题。

函数声明提升本身不会报错,但会让代码执行顺序和开发者直觉产生偏差,尤其在混用函数声明与函数表达式、或同名变量/函数共存时,容易出现“看似能运行却逻辑不对”的问题。
函数声明优先于同名变量提升
当函数名和变量名相同时,函数声明会完整提升到作用域顶部,而变量赋值不会。这导致调用发生在赋值前,实际执行的是函数而非后续赋值的值。
- 例如:
foo(); // 输出 12,function foo() { return 12; },var foo = 42;—— 调用的是提升后的函数,不是后来赋值的数字 - 但如果写成
var foo = function() { return 42; };,则foo()在声明前调用会报TypeError,因为函数表达式不提升 - 这种差异让团队协作中难以快速判断某处调用到底执行的是哪个定义,尤其在大型模块里分散声明时
函数表达式不提升,但变量声明仍会
使用 const 或 let 声明函数表达式时,虽然变量本身被提升,但处于暂时性死区(TDZ),访问即报错;而 var 声明函数表达式,变量会被初始化为 undefined,调用时报 TypeError: not a function,错误类型不同,排查路径也不同。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
bar(); // TypeError: bar is not a function,var bar = function() {}; -
baz(); // ReferenceError: Cannot access 'baz' before initialization,let baz = function() {}; - 调试时若只看报错信息不细查声明方式,容易误判是语法错误或作用域问题
条件语句中的函数声明行为不一致
在非严格模式下,函数声明出现在 if、for 等块级结构中时,部分浏览器会将其提升至外层函数作用域,但规范未强制要求,导致跨环境行为差异。
- Chrome 和 Firefox 可能允许
if (true) { function test() {} }后直接调用test(),而 Safari 或旧版 Edge 可能报ReferenceError - ES6 明确不鼓励块级函数声明,推荐改用函数表达式或
let绑定,但存量代码中仍常见 - 这类问题往往只在特定浏览器或构建工具链(如某些 Babel preset)下暴露,本地开发无异常,上线后才出问题
调试时看不到真实执行顺序
开发者工具的断点和堆栈显示的是运行时状态,不会还原预编译后的逻辑结构。比如一个函数在 if 块内声明,调试器里看到它“突然可用”,但源码里找不到前置声明,容易误以为是闭包或全局污染。
- Chrome DevTools 的 “Sources” 面板默认显示原始代码,不会展示提升后的等效逻辑
- 单步执行时,变量首次读取为
undefined或函数体,但光标停在赋值行之前,缺乏上下文提示这是提升所致 - 配合异步回调(如
setTimeout(() => console.log(foo), 0))时,更难定位是提升时机还是执行时机问题
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










