函数表达式与箭头函数的核心差异在于提升行为、this/arguments绑定及构造函数能力:函数表达式(var声明时仅变量名提升)有独立this和arguments,可作构造函数;箭头函数无this/arguments,不可new,依赖外层词法作用域。

函数表达式和箭头函数在变量声明上的核心差异,不在于“能不能声明变量”,而在于它们自身是否会被提升(hoisting)、是否拥有自己的 this 和作用域绑定,以及是否能作为构造函数使用——这些间接但深刻地影响了变量声明的上下文行为和可访问性。
函数表达式:有命名/匿名之分,支持变量提升(仅声明)
当用 const fn = function() { ... } 这种方式定义时,是典型的函数表达式。注意:变量声明本身(如 const fn)不会被提升,但函数体也不会被提升;整个赋值语句按顺序执行。若写成 var fn = function() {},则 var fn 的声明会被提升(初始化为 undefined),但右侧函数体仍不会提前执行。
-
不能重复声明同名变量(尤其用
let/const时),否则报错 -
函数内部可访问外部作用域变量,也拥有独立的
arguments对象 - 若用
function name() {}形式(命名函数表达式),函数名只在内部可用,不影响外部变量名
箭头函数:无自己的 this、arguments,也不支持 new
箭头函数本身不是“声明”,而是表达式,必须赋值给变量或作为参数传入。它没有自己的执行上下文,因此不绑定 this、arguments、super 或 new.target,全部沿用外层函数作用域的值。
-
不能用作构造函数,调用
new fn()会抛出 TypeError -
没有
arguments对象,需用剩余参数...args替代 -
无法通过
fn.name获取有意义的函数名(通常为空字符串或 "anonymous") - 若写成
const fn = () => {},变量fn遵循const规则(不可重新赋值),但函数体本身不可变性与普通函数一致
变量声明方式决定作用域,而非函数类型
真正影响变量可见性和生命周期的是 var / let / const 的声明方式,不是函数类型。例如:
-
let fn = () => {}:块级作用域,不可重复声明,不可提升 -
var fn = function() {}:函数作用域,声明提升,允许重复var声明(但赋值不提升) -
const fn = () => {}:块级作用域,必须初始化,且不能重新赋值(但对象属性仍可修改)
常见误判点:this 绑定带来的“变量可见性”错觉
很多人觉得箭头函数“能访问外部变量”,而普通函数“不能”,其实是误解。两者都能访问外部变量(闭包机制相同)。真正区别在于:箭头函数内部的 this 指向外层词法作用域的 this,而函数表达式中的 this 取决于调用方式(如方法调用、call/bind 等)。这会影响你通过 this.xxx 访问的变量是否如预期存在。
- 在对象方法中,
function() { console.log(this.val) }的this是对象本身;() => console.log(this.val)的this是定义时外层的this(常为全局或 undefined) - 这种差异常被误读为“变量声明范围不同”,实则是
this绑定时机不同










