函数声明在es6模块中仅在本模块顶层作用域预编译阶段提升,按依赖图自底向上执行,不跨模块生效,且受import顺序严格约束。

函数声明在模块化脚本中仍遵循标准的预编译(提升)规则,但执行时机受模块加载机制约束——它不会被提前到整个页面解析前,而是严格按模块依赖图和 HTML 中 <script type="module"></script> 的出现顺序同步执行。
模块内函数声明仍会被提升
在一个 ES6 模块文件(如 utils.js)中,函数声明(function foo() { })会在该模块自身的**顶层作用域预编译阶段**被提升,早于任何语句执行。这意味着:
- 模块内部可安全在声明前调用该函数;
- 同名函数声明会覆盖前面的,以最后定义为准;
- 但变量声明(
var)和函数声明共存时,函数提升优先级高于var。
模块间执行顺序由 import 依赖链决定
ES6 模块的执行不是按 HTML 标签位置线性排队,而是构建静态依赖树后自底向上执行:
-
import语句在解析阶段即确定依赖关系,被导入模块总先于导入者执行; - 例如
A.js导入B.js,则B.js中所有顶层代码(含函数声明与调用)必先完成,A.js才开始执行; - 这种顺序是确定的、可预测的,不随网络延迟或文件大小变化。
函数声明不跨模块“提前生效”
模块顶层的函数声明只在本模块作用域内提升,对外不可见——除非显式 export:
- 即使
B.js声明了function helper(),A.js也无法在import之前就使用它; -
import触发的是模块整体执行,而非“仅导入函数声明”,因此依赖模块必须已完全执行完毕; - 若
B.js中函数依赖尚未初始化的全局状态(如window.gVar.scene),错误发生在执行期,而非提升期。
避免常见陷阱的实践建议
为确保函数可用性与初始化顺序一致:
- 导出函数优先于导出未初始化的变量(如
export function init() { ... }而非export let config后再赋值); - 避免在模块顶层直接调用依赖其他模块状态的函数,改用
export函数供调用方按需执行; - 慎用
async加载模块——它破坏执行顺序保证,导致函数可能尚未定义就被调用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











