javascript函数声明会被完全提升至作用域顶部,支持前置调用;c语言函数声明仅为编译期接口契约,不执行也不提升;函数表达式在js中不提升函数体,需赋值后调用;es模块顶层禁止函数声明,须用表达式或导出语法。

函数声明在不同代码环境中表现差异明显,核心在于“是否被提升(hoisting)”以及“作用域可见性规则”这两点。C语言和JavaScript虽都用function或类似语法,但底层机制完全不同,不能套用同一套理解。
JavaScript 中的函数声明:全作用域提升,可前置调用
在 JavaScript 全局或函数作用域中,function foo() { } 是函数声明,会被完全提升到作用域顶部——包括函数名和函数体。这意味着:
- 可以在声明语句之前调用该函数,不会报错;
- 即使声明在
if块内(非严格模式),也可能被提升到外层函数顶部; - 同名函数声明会覆盖前面的声明(后者生效)。
C 语言中的函数声明:仅接口告知,不执行也不分配内存
C 语言里的函数声明(如 int add(int a, int b);)本质是编译期契约,它:
- 不生成任何可执行代码,也不分配栈空间;
- 只让编译器知道“将来会有这样一个函数”,用于实参类型和数量校验;
- 必须出现在调用前(除非定义在调用前),否则编译失败;
- 常放在头文件中统一管理,源文件包含该头文件后,编译器能比对声明与定义是否一致。
函数表达式在 JS 中的行为:不提升,需先赋值再使用
像 const foo = function() {} 或 var foo = function() {} 属于函数表达式,它:
- 受变量提升影响(
var声明提升但初始化不提升,const/let不提升); - 函数本身没有名字绑定(匿名),名字仅用于调试或递归调用;
- 必须等赋值语句执行完才能调用,否则报
ReferenceError或undefined is not a function。
模块环境(ESM / CommonJS)下的声明限制
在现代模块系统中,函数声明行为进一步受限:
- ES 模块顶层不允许出现函数声明(语法错误),必须用函数表达式或导出语句包裹;
- CommonJS 中
module.exports = function() {}是常见写法,函数以值形式导出,无提升特性; - TypeScript 中声明需配合
declare关键字用于类型描述,不参与运行时逻辑。











