普通函数的this由调用者决定,箭头函数无this,继承外层普通函数的this;bind/call/apply对箭头函数无效;对象字面量中箭头函数的this不指向该对象,class字段箭头函数因在构造函数中执行而指向实例。

普通函数的 this 是调用时才确定的
不是定义时,也不是写在哪一层作用域里就固定了——关键看「谁调用了它」。比如 obj.method(),this 就是 obj;但把 method 单独提出来赋值给变量再调用,this 就变成 undefined(严格模式)或全局对象(非严格模式)。
常见踩坑场景:
- 事件回调里直接传函数:
btn.addEventListener('click', obj.handleClick)→this不再是obj - 定时器中调用方法:
setTimeout(obj.method, 100)→ 同样丢失this - 数组方法如
map、forEach的回调没显式绑定this,默认是全局或undefined
解决办法常用 .bind()、.call()、.apply(),或者用箭头函数替代(见下一条)。
箭头函数没有自己的 this,它继承外层普通函数的 this
箭头函数不绑定 this,也不支持 call/apply/bind 改变它的 this。它只是「沿作用域链向上找最近的一个普通函数的 this 值」。
立即学习“Java免费学习笔记(深入)”;
注意几个关键点:
- 如果箭头函数最外层没有普通函数(比如直接写在全局作用域),那它的
this就是全局对象(浏览器里是window,Node.js 是global) - 对象方法里写箭头函数,
this不指向该对象,而是指向定义时所在函数的this—— 所以常用于避免回调中this丢失 -
class里定义的箭头函数属性(如handleClick = () => { ... }),this指向实例,因为类体顶层代码其实是在构造函数执行上下文中解析的
示例:
const obj = {
name: 'test',
regular() {
console.log(this.name); // 'test'
setTimeout(function() {
console.log(this.name); // undefined(严格模式)
}, 100);
setTimeout(() => {
console.log(this.name); // 'test',继承 regular 的 this
}, 100);
}
};
bind、call、apply 对箭头函数无效
试图用这些方法强行改箭头函数的 this,不会报错,但也不会生效。因为箭头函数根本没自己的 this 绑定,自然无法被重绑定。
验证方式很简单:
const arrow = () => console.log(this);
arrow.call({x: 1}); // 输出仍是定义时的 this(比如 window),不是 {x: 1}
arrow.bind({y: 2})(); // 同样无效
所以别在箭头函数上白费力气做 bind,要改 this,得换普通函数,或者调整外层函数的调用方式。
容易忽略的边界:对象字面量里的箭头函数和 class 字段
很多人以为「对象里写的箭头函数,this 就是这个对象」,这是错的。对象字面量本身不创建函数执行上下文,里面的箭头函数依然看外层。
比如:
const obj = {
name: 'outer',
fn: () => console.log(this.name)
};
obj.fn(); // 输出 undefined 或 'outer' 取决于外层 this,跟 obj 无关
而 class 中的字段语法(handle = () => {})之所以能绑定实例,是因为它本质是「在构造函数中对实例赋值」,此时外层 this 就是新实例。这和对象字面量的执行时机完全不同。
真正决定箭头函数 this 的,从来不是它「在哪写的」,而是「在哪执行的」——更准确地说,是「它被定义时,所处的最近一个普通函数执行上下文的 this 是什么」。











