函数执行时的this取决于调用者和调用方式:隐式绑定看“点左边是谁”,显式绑定用call/apply/bind强制指定,且显式优先级高于隐式;箭头函数无this,继承外层词法作用域。

函数执行时的 this 不是写死的,它取决于“谁调用”和“怎么调用”。隐式绑定靠调用位置自动确定,显式绑定靠代码手动指定——两者常共存、易混淆,搞清它们的区别和协作方式,才能避免常见 bug。
隐式绑定:看“点左边是谁”
当函数以 obj.method() 形式被调用时,this 自动指向点号前的对象(即最近一层调用者),这是最自然也最易被破坏的绑定方式。
- 只认“最后一层对象”:即使
obj1.obj2.method(),this 也只指向obj2,和obj1无关 - 隐式丢失很常见:把方法赋值给变量、传入回调、解构提取,都会让 this 脱离原对象,退化为默认绑定(非严格模式下是
window或global) - 例子:
const btn = document.getElementById('x'); btn.onclick = handler;中,this 指向btn;但若写成const fn = btn.onclick; fn();,this 就不再是btn
显式绑定:用 call/apply/bind 强制指定
当你不能依赖调用位置,或需要临时/永久改变上下文时,就用显式绑定。三者核心区别在于执行时机和返回结果:
-
func.call(obj, a, b):立即执行,参数逐个传 -
func.apply(obj, [a, b]):立即执行,参数用数组传 -
func.bind(obj, a, b):不执行,返回一个新函数,this 和部分参数已固化 - bind 创建的是“硬绑定”,后续再用
call或apply也无法覆盖它 - 注意:如果传入
null或undefined作为 thisArg,非严格模式下仍会绑定到全局对象
隐式 + 显式:谁优先?
显式绑定优先级高于隐式绑定。也就是说,即使一个函数是通过对象方法形式调用的,只要内部用了 call/apply/bind,最终 this 就由显式调用决定。
- 例子:
const obj = { name: 'Alice', foo() { console.log(this.name); } }; const bar = obj.foo.bind({ name: 'Bob' }); bar();→ 输出Bob,不是Alice - 再如:
obj.foo.call({ name: 'Charlie' });→ 即使是obj.foo,this 也以call指定的为准 - 但箭头函数不参与这套规则——它没有自己的 this,始终继承外层词法作用域的值
实战建议:什么时候该用哪种?
日常开发中,别硬记规则,按场景选策略:
- 对象方法内直接访问自身属性 → 用隐式绑定(最简洁,如
user.getName()) - 事件回调、定时器、异步操作中丢失 this → 优先用箭头函数,或提前
bind,或用call/apply在触发时重绑 - 工具函数需要适配不同对象 → 用
call或apply(如[].forEach.call(arrayLike, cb, thisArg)) - 创建预设上下文的复用函数 → 用
bind(如const logUser = logger.bind(user)) - 不确定调用方式时,可在函数开头加
if (this === undefined) throw new Error('this not bound')主动报错,比静默出错更利于调试

















