函数声明以function开头且不在表达式中,可提升、具名可见;函数表达式前置有操作符或括号,不可提升、名字仅内部有效。

看语句开头和所处位置就能快速区分:以 function 关键字开头、且不在表达式上下文中的,是函数声明;其他情况基本都是函数表达式。
一看语句是否以 function 开头
这是最直接的判断依据:
- 函数声明一定以 function 开头,后面紧跟着函数名,例如:
function add(a, b) { return a + b; } - 函数表达式不会以 function 开头——它前面总有东西,比如赋值操作符(
=)、括号((function(){}()))、逗号(数组或参数列表中)、return 后面等。例如:const add = function(a, b) { return a + b; };或(function() { console.log('hi'); })();
二看能否出现在块级结构内部
语法合法性也是关键线索:
- 函数声明不能合法地写在
if、for、try等块内部(尽管某些引擎容忍,但属于非标准行为,应避免) - 函数表达式可以自由出现在任何表达式允许的位置:条件分支里、数组方法回调中、对象属性值、立即执行场景等。例如:
if (x) { const fn = function() {}; }是完全合法的
三看提升(hoisting)表现是否一致
运行时行为能反向验证定义类型:
- 函数声明会被**完全提升**:函数名和函数体都提前可用,可在声明前调用
- 函数表达式只提升变量声明(仅限
var),函数体仍留在原处;用let或const时,连变量名都不提升,提前访问直接报ReferenceError - 所以如果某段
function xxx() {}写在xxx()调用之后却能运行,那它就是函数声明;反之报错,大概率是表达式被误当声明用了
四看名字是否对外可见
命名细节也透露本质:
- 函数声明的名称一定绑定到当前作用域,可直接通过函数名访问
- 函数表达式即使写了名字(如
const f = function named() {}),这个named也只在函数内部有效,外部无法调用或引用 -
f.name会返回"named",但typeof named是undefined

















