函数声明会整体提升,可先调用后定义;函数表达式仅变量声明提升或不提升,函数体不可提前访问;声明位置受限于作用域,表达式更灵活;声明名全局可见,表达式名仅内部有效;声明适用于核心逻辑,表达式适用于值场景如iife、回调等。

提升行为完全不同
函数声明在代码执行前就完成整个定义的注册,名字和函数体一起被提升到作用域顶部,所以可以先调用后写声明:
function say() { console.log('hi'); }
say(); // ✅ 正常输出
函数表达式只提升变量声明(var)或不提升(let/const),函数体本身不会提前可用:
const fn = function() { console.log('bye'); };
fn(); // ❌ 报错,此时 fn 还未赋值
let/const 声明的函数表达式甚至进“暂时性死区”,连 typeof 都会报 ReferenceError。
语法位置限制严格程度不同
函数声明只能出现在顶层作用域或函数体内,不能直接写在 if、for、try 等块级结构里:
if (true) { function foo() {} } // ❌ 非标准,各引擎处理不一致,严格模式下报错
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
函数表达式没有这个限制,可自由嵌入任意表达式上下文:
- if (ok) { const handler = function() {}; }
- [1,2].map(function(x) { return x * 2; })
- btn.addEventListener('click', function() {})
名称绑定的作用域范围不同
函数声明的名字是作用域内的正式标识符,外部可直接访问:
function greet() {}
greet(); // ✅
typeof greet === 'function'; // ✅
函数表达式的名称(如果写了)仅在函数内部有效,不创建外部绑定:
const talk = function hello() { console.log(hello); };
talk(); // ✅ 输出 hello
hello(); // ❌ ReferenceError
talk.name // 'hello' —— name 属性保留,但没对外暴露
适用场景由语义决定
函数声明适合定义模块级、可复用的核心逻辑,强调“它是一个函数”;
函数表达式强调“它是一个值”,天然适配以下场景:
- 立即执行:(function() {})()
- 作为参数传递:setTimeout(function() {}, 1000)
- 动态生成或闭包封装:const createAdder = (x) => function(y) { return x + y; }
- 对象方法定义:const obj = { method: function() {} }
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










