函数表达式的this取决于调用时的上下文:直接调用指向全局或undefined,对象方法调用指向该对象,call/apply/bind可显式指定,new调用指向新实例;箭头函数则静态继承外层this。

函数表达式本身不绑定 this,它的 this 值完全取决于**调用时的上下文**,而不是定义位置。这是和箭头函数最核心的区别。
普通函数表达式的 this 由调用方式决定
当用函数表达式声明一个函数(如 const fn = function() { console.log(this); };),它的 this 不是固定在定义时的作用域,而是看它被谁调用、怎么调用:
- 直接调用(
fn()):非严格模式下指向全局对象(浏览器中是window),严格模式下为undefined - 作为对象方法调用(
obj.fn()):指向该对象(obj) - 用
call/apply/bind显式指定:this就是传入的第一个参数 - 作为构造函数调用(
new fn()):指向新创建的实例
常见问题:回调中 this 丢失
把函数表达式当作回调传入(比如事件监听、定时器、数组方法),容易丢失原本期望的 this:
const obj = {
name: 'Alice',
sayHi: function() { console.log('Hi, ' + this.name); }
};
setTimeout(obj.sayHi, 1000); // 输出 "Hi, undefined"(非严格模式下可能是 window)
原因:这里传的是函数引用 obj.sayHi,但调用时已脱离 obj 上下文,this 不再指向 obj。
解决办法有三种:
- 用
bind预绑定:setTimeout(obj.sayHi.bind(obj), 1000) - 用闭包保存
this:const self = this; setTimeout(function() { self.sayHi(); }, 1000) - 改用箭头函数(但注意:箭头函数没有自己的
this,它继承外层作用域的this)
与箭头函数的关键区别
箭头函数不创建自己的 this,它会沿作用域链向上查找外层普通函数或全局作用域的 this 值,并且这个绑定是静态的、不可更改的。而函数表达式有自己的 this 绑定逻辑,是动态的、可被调用方式覆盖的。
所以,如果你需要函数内部的 this 稳定地指向某个对象,又不想手动 bind,可以考虑在合适的位置用箭头函数;但如果需要灵活控制 this(比如写通用工具函数、构造器、或要支持 call 调用),就必须用普通函数表达式,并明确管理调用上下文。
小技巧:快速判断 this 指向
看到一个函数表达式,别急着猜 this 是什么,先问一句:这个函数是在哪被调用的?调用时前面有没有点(.)?有没有用 call/apply/bind?是不是 new 调用? 答案就藏在调用那一行代码里。

















