this 是函数调用时确定的执行上下文对象,取决于调用方式:普通调用指向全局或 undefined,方法调用指向点号前对象,构造调用指向新实例,显式绑定由 call/apply/bind 指定;箭头函数无 this,继承外层。
this 是什么this 不是函数定义时绑定的,而是在函数被调用时才确定的——它指向**当前执行上下文中的对象**。这个对象不一定是定义函数的那个对象,甚至不一定是“拥有”该函数的对象。它的值完全取决于函数怎么被调用,而不是怎么被声明。
this 指向绝大多数情况下,this 的值由函数的调用形式决定,而非位置或词法作用域:
foo() → 在非严格模式下指向 window(浏览器)或 globalThis(Node.js),严格模式下为 undefined
obj.method() → this 指向 obj(即点号左边的
对象)new Foo() → this 指向新创建的实例对象func.call(obj, ...)、func.apply(obj, [...])、func.bind(obj) → this 强制绑定为 obj
注意:箭头函数没有自己的 this,它会沿作用域链向上查找外层非箭头函数的 this 值,且无法被 call/apply/bind 改变。
这些地方的 this 很容易意外丢失或指向错误对象:
const obj = { name: 'a', say() { console.log(this.name) } };
const fn = obj.say;
fn(); // this 是 undefined(严格模式)→ 输出 undefined,不是 'a'document.addEventListener('click', obj.say); // 点击时 this 指向 document,不是 objsetTimeout(obj.say, 100); // this 指向全局,不是 obj
解决办法常用三种:bind(obj)、function() { obj.say() } 包一层、或改用箭头函数(前提是外层 this 正确)。
this 指向别猜,看调用点——找到函数名前最近的「点操作符」或「call/apply/bind 参数」:
obj.method() → 看 obj.,this === obj
fn.call(other) → 看 call(other),this === other
new Ctor() → this 是新实例new、没显式绑定 → 默认绑定,再看是否严格模式箭头函数跳过这一步,直接继承外层函数的 this;类方法体内的普通函数仍遵循上述规则,除非显式绑定。
最常被忽略的是:事件回调和异步回调里 this 的隐式丢失,以及把方法当纯函数传参时未做绑定。写之前先问一句:“这个函数被谁调用?”