函数表达式和变量赋值仅声明提升、不初始化,赋值严格按代码顺序执行;预编译阶段只声明变量为undefined,执行阶段才赋值函数对象或计算右值并赋值,故不能在赋值前调用。

函数表达式和变量赋值在 JavaScript 中的执行顺序,关键在于“预编译阶段”和“执行阶段”的分工。它们不会像函数声明那样被完全提升(hoisted),而是遵循“声明提升但不初始化”的规则,且赋值操作严格按代码顺序执行。
函数表达式:只提升变量名,不提升函数体
当你写 var fn = function() { ... }; 时:
- 预编译阶段:仅将
fn声明为undefined(类似var fn;) - 执行阶段:遇到这一行才真正把函数对象赋值给
fn - 因此,在赋值语句之前调用
fn()会报错:TypeError: fn is not a function
变量赋值:严格从上到下,右值先求值
赋值语句 a = b + c 的执行逻辑是:
- 先计算等号右边的表达式(
b + c),得到结果 - 再把结果赋给左边变量
a - 若右边含函数调用,该函数会立即执行并返回值,然后才完成赋值
混合场景:变量声明 + 函数表达式 + 调用
看这个例子:
console.log(fn); // undefined
var fn = function() { return 42; };
console.log(fn()); // 42
console.log(fn); // ƒ () { return 42; }
说明:
- 第一行能访问
fn(因var声明被提升),但值是undefined - 第二行才真正把函数对象赋过去
- 第三行已可正常调用
注意与函数声明的区别
对比 function fn() { ... }:
- 整个函数声明会被“完全提升”——函数名和函数体都在预编译阶段就准备好
- 所以可以在声明前调用(只要它是函数声明,不是表达式)
- 而函数表达式不具备这种能力,它本质是“赋值操作”,必须等到执行到那行才生效











