this的底层原理是函数调用时引擎动态绑定:new调用→新对象;call/apply/bind→手动指定;obj.method()→点前对象;独立调用→全局或undefined;箭头函数继承外层this。

讲 this 的底层原理,关键不是背规则,而是抓住一个动作:**函数被调用的那一刻,JavaScript 引擎当场给它配一个 this**。这个“配”不是看函数写在哪,而是看它“怎么被叫出来的”。就像点外卖——你打给哪家店、用什么方式打(电话/APP/到店),决定谁来接单;this 也一样,调用方式决定 this 是谁。
1. this 不是“属于函数”的,而是“属于这次调用”的
函数本身没有固定 this。同一个函数,被不同对象调用,this 就不同:
- obj.sayHi() → this 是 obj
- other.sayHi() → this 是 other
- sayHi()(单独调)→ this 是 window 或 undefined
这说明:引擎不记“函数是谁写的”,只看“这次是谁在执行它”。就像同一把钥匙,开哪扇门,取决于你把它插进哪个锁孔。
2. 引擎按固定顺序“找人”配 this(优先级从高到低)
每次调用函数时,引擎像查流程表一样,逐条判断:
-
new 调用? → this 是新造出来的空对象(如
new Person()) -
用了 call/apply/bind? → this 就是你手动传进去的那个对象(如
fn.call(obj)) -
是 obj.method() 这样调的? → this 是点号前面那个对象(
obj) -
以上都不是,就直接 fn()? → 默认绑定:非严格模式下是全局对象(
window),严格模式下是undefined
注意:箭头函数不参与这张表——它压根不自己配 this,而是“抄”外层函数调用时的 this,而且抄完就定死,call/bind 都改不了。
3. 常见“丢失 this”其实就一个原因:调用方式变了
比如:
-
const fn = obj.sayHi;—— 这只是复制函数,没调用 -
fn();—— 这才是调用,但已变成“独立调用”,触发默认绑定
不是 this “丢了”,是它从来就没绑定到 obj 上——因为调用时已经脱离了 obj. 这个上下文。解决方法也很直白:要么用 obj.sayHi.bind(obj) 锁住,要么用箭头函数“继承”,要么调用时写成 obj.sayHi() 不拆开。
4. 浏览器事件里的 this 是个特例,但逻辑一致
写 btn.onclick = handler,点击时引擎自动以 btn.handler() 方式调用,所以 this 就是 btn。用 addEventListener 也一样——引擎内部做了隐式绑定,让你不用手写 btn.handler.call(btn)。











