this:一张规则表讲清绑定优先级,箭头函数为什么“没 this”?
面试速答(30 秒版 TL;DR)
this不是“定义时决定”,而是调用时按规则绑定(箭头函数例外)。- 绑定规则优先级(从高到低):
new绑定 >bind硬绑定 >call/apply显式绑定 > 隐式绑定(obj.fn()) > 默认绑定(严格模式undefined,非严格模式window/globalThis)。 - 箭头函数没有自己的
this:它捕获外层词法作用域的this(lexical this),call/apply/bind改不了。 - 事件处理、回调函数、解构赋值后的方法调用是
this丢失的高频坑;用bind、箭头函数、或显式调用修复。
心智模型:this 只看“怎么调用”
不要背“this 指向谁”,背“调用表达式长什么样”更稳。
// 同一个函数,不同调用方式,this 不同
function f() {
return this;
}
f(); // 默认绑定:严格模式 undefined;非严格模式 globalThis
({ f }).f(); // 隐式绑定:{ f }
f.call({ x: 1 }); // 显式绑定:{ x: 1 }
new f(); // new 绑定:新对象
绑定优先级流程图(背这一张)
隐式绑定的坑:方法被“拿出来”就丢了
const obj = {
x: 1,
getX() {
return this.x;
},
};
obj.getX(); // 1
const getX = obj.getX;
getX(); // 严格模式:TypeError(this 为 undefined);非严格:undefined
修复方式(面试常见答法):
- 用
bind固定:const getX = obj.getX.bind(obj) - 用包装函数显式调用:
() => obj.getX() - 在类里用字段箭头函数(见
class章节):method = () => { ... }
箭头函数:为什么“没 this”,却又能用 this?
箭头函数的 this 来自外层最近的普通函数/全局 this。
const obj = {
x: 1,
a() {
const arrow = () => this.x;
return arrow();
},
};
obj.a(); // 1
关键点:
- 箭头函数的
this不是运行时绑定,因此arrow.call({ x: 2 })也不会变。 - 箭头函数也没有
arguments、prototype,不能new。
典型题 & 标准答法
Q1:obj.fn() 一定让 this === obj 吗?
不一定。只要“调用表达式”不是 obj.fn(),隐式绑定就可能丢失,例如:
const obj = { x: 1, fn() { return this.x; } };
const { fn } = obj;
fn(); // this 丢失
Q2:setTimeout(obj.fn, 0) 里 this 是什么?
this 丢失。因为传给定时器的是“裸函数引用”,等同于默认绑定(严格模式 undefined)。
常见追问
call/apply/bind区别:call传参列表;apply传参数组;bind返回新函数并固定this。null/undefined作为call/apply的 thisArg:非严格模式会被替换为globalThis;严格模式保持null/undefined。
易错点/坑
this不是指向“函数定义的对象”,而是指向“调用点绑定的对象”。- 回调函数(事件、Promise、数组遍历)最容易丢
this,尤其是把方法当参数传递。
速记要点(可背诵)
this看调用点;箭头函数看外层作用域。- 优先级:
new>bind>call/apply>obj.fn()> 默认绑定。