JavaScript中this在调用时动态绑定:普通函数直接调用时非严格模式指向window、严格模式为undefined;对象方法需obj.fn()形式调用才绑定obj;箭头函数无this,继承定义时外层this;call/apply/bind可显式指定this。

JavaScript 中的 this 不是定义时决定的,而是调用时动态绑定的——你写的函数里写的是 this,但真正指向谁,得看它「怎么被调用」。
普通函数调用时的 this 指向全局或 undefined
在非严格模式下,直接调用函数(如 foo()),this 指向全局对象(浏览器中是 window);严格模式下是 undefined。这个行为和函数在哪定义、是否嵌套完全无关。
- 容易误以为「写在对象方法里,
this就一定指向该对象」——其实只要把方法单独拿出来调用,就失效了 -
setTimeout(obj.method, 100)或button.addEventListener('click', obj.handleClick)都属于这种丢失场景 - 解决方式不是「记住规则」,而是主动控制:用
.bind(obj)、箭头函数(仅限定义时捕获外层this)、或包装成() => obj.method()
对象方法调用时的 this 指向调用者
只有形如 obj.fn() 这种「点号加括号」的调用方式,this 才绑定到点号前的对象。注意:这个对象必须是「调用时实际存在的引用值」,不是「看起来像」。
-
const fn = obj.method; fn();→this不再是obj -
(obj.method)();和obj?.method?.();在可选链下,如果中间为null/undefined,会报错而非静默绑定到全局 - 箭头函数不能用作对象方法来“修复”
this,因为它根本不会创建自己的this,只沿作用域链向上找——所以obj = { fn: () => this }中的this是定义时外层的,不是obj
call / apply / bind 如何强制指定 this
这三个 API 是唯一能显式覆盖默认绑定规则的方法。它们的区别只在参数传递形式,核心都是「把第一个参数设为本次执行的 this 值」。
立即学习“Java免费学习笔记(深入)”;
-
fn.call(obj, a, b):传参用逗号分隔 -
fn.apply(obj, [a, b]):传参用数组 -
const bound = fn.bind(obj, a); bound(b);:返回新函数,预设this和部分参数 - 注意:
bind返回的函数无法再被call或apply改变this(除非用new,但那会忽略绑定的this)
箭头函数没有自己的 this,但容易被误用
箭头函数不绑定 this,也不支持 call/apply/bind 修改它。它的 this 值由词法作用域决定——即函数定义时所在上下文的 this。
const obj = {
name: 'test',
regular() {
return this.name; // 'test'
},
arrow: () => {
return this.name; // 全局中是 undefined(严格模式)
},
wrapper() {
const inner = () => this.name;
return inner(); // 这里 this 是 obj,因为 wrapper 的 this 是 obj
}
};
- 不要在需要动态
this的地方(比如 Vue/React 类组件的方法)滥用箭头函数声明实例方法 - 在事件回调、定时器、Promise 回调中用箭头函数,通常是为了避免手动
bind,前提是外层函数的this已正确绑定 - 构造函数不能是箭头函数——它没有
this绑定机制,也没有prototype
真正卡住人的从来不是「规则有多少条」,而是调用链中某一层悄悄改变了上下文,比如解构赋值、事件监听器传参、高阶函数返回、Proxy 包裹对象……盯住「谁在调用」比背绑定优先级更可靠。











