普通函数直接调用时,非严格模式下this指向全局对象,严格模式下为undefined;对象方法调用时this指向该对象,但提取后会丢失;箭头函数无this,继承外层;new和call/apply/bind可显式控制this。
在非严格模式下,function foo() { console.log(this); } 直接调用 foo(),this 指向 window(浏览器)或 globalThis(Node.js);严格模式下则为 undefined。这点极易被忽略,尤其在封装工具函数时——你以为在操作某个上下文,实际却在污染全局或触发 TypeError。
实操建议:
"use strict"),避免隐式绑定带来的不确定性window 绑定,现代代码
应显式传参或使用箭头函数替代this 是否符合预期当写成 obj.method(),this 就是 obj。但一旦把方法抽出来赋值给变量,比如 const fn = obj.method; fn();,就退化为上一种情况——this 不再是 obj。
常见错误现象:Uncaught TypeError: Cannot read property 'x' of undefined,尤其在事件回调、定时器、Promise 回调里丢失上下文。
解决方式(按推荐顺序):
bind 显式绑定:setTimeout(obj.method.bind(obj), 100)
setTimeout(() => obj.method(), 100)
method = () => { ... }
const { method } = obj; 是高危操作,除非你立刻 bind 或包装箭头函数不绑定 this,它直接继承外层函数执行时的 this 值。这意味着它无法通过 call/apply/bind 改变 this,也不能作为构造函数使用。
典型误用场景:
const obj = { fn: () => console.log(this) } —— 这里的 this 是定义时的外层上下文,不是 obj
setTimeout(obj.arrowFn.bind(obj), 100) —— bind 无效,因为箭头函数无视所有显式绑定正确做法:需要动态 this 就用普通函数;需要固化外层 this(如 React 类组件中处理事件)才用箭头函数。
new Foo() 时,this 指向新创建的实例对象;Foo.call(obj, ...) 则强制让 this 指向 obj。这两者优先级最高,能覆盖其他规则。
注意点:
bind 返回的函数,即使再 bind 一次,也无法改变第一次绑定的 this(返回的是“硬绑定”函数)call 和 apply 是立即执行,而 bind 返回新函数,适合预设参数 + 后续调用new,会报 TypeError: xxx is not a constructor
最易被忽略的细节:class 内部的普通方法(非箭头)在被提取后,this 依然会丢失——class 并不自动绑定方法,这是设计使然,不是 bug。