← [ BACK_TO_NOTES ]

this 关键字

按调用方式解释 this 绑定规则,覆盖默认绑定、隐式绑定、显式绑定、new 绑定与箭头函数词法 this。

#concept #growing #dev #javascript #ecmascript

[!info] related notes

this 关键字

这个概念为什么出现

回调里 this 突然变成 undefined,事件处理函数里读不到组件字段,setTimeout 后方法丢失接收者——这些问题几乎都不是“语法记错”,而是 this 由调用方式决定 没建立起来。

[!abstract] 一句话理解 普通函数的 this 在调用时绑定;箭头函数的 this 在定义时词法继承外层。

最小可运行示例

场景:库存服务对象的方法被当成回调传递

// 保存为 this-demo.mjs,以 ES 模块运行。
const inventoryService = {
  warehouse: 'A仓',
  label(sku) {
    // 普通未绑定方法按 obj.method() 调用时,this 是该 obj
    return this.warehouse + '::' + sku
  },
}

console.log(inventoryService.label('SKU-1')) // 隐式绑定:A仓::SKU-1

const detached = inventoryService.label
try {
  // 本例作为 ES 模块运行:独立调用时 this 为 undefined,属性读取抛 TypeError
  console.log(detached('SKU-2'))
} catch (e) {
  console.log('detached failed:', e.message)
}

console.log(detached.call({ warehouse: 'B仓' }, 'SKU-3')) // 显式绑定
console.log(inventoryService.label.bind({ warehouse: 'C仓' })('SKU-4'))

const arrowService = {
  warehouse: 'A仓',
  label: (sku) => {
    // 箭头函数:this 不绑定到 arrowService
    return (typeof this === 'undefined' ? 'no-this' : this.warehouse) + '::' + sku
  },
}
console.log(arrowService.label('SKU-5')) // 模块顶层 this 是 undefined:no-this::SKU-5

建议运行:

node this-demo.mjs
# 对照 CJS 时另存为 .cjs;顶层 this 与严格模式条件不同

结合场景关注点

  1. 取方法再调用会丢接收者。
  2. call/apply/bind 显式指定 this。
  3. 箭头函数不能靠 bind 改 this 语义来“变成方法接收者”。

核心规则(普通函数)

调用形式this 直觉
fn()undefined(严格)/ 全局对象(非严格、非模块)
obj.fn()obj
fn.call(x) / apply / bind严格普通函数保留 x;非严格函数将 null/undefined 替换为全局对象,原始值会装箱
new Fn()普通基类构造器中为新实例;显式返回对象可替换最终构造结果
addEventListener 的未绑定普通函数回调通常为 event.currentTarget;箭头函数与框架包装另论

已 bind 的普通函数再用 call/apply 不能替换其绑定的 this;对可构造的 bound function 使用 new 时则忽略绑定的 this。箭头函数不可 new,也不能用 call/apply/bind 改 this。

运行环境也要区分:ES 模块顶层 this 为 undefined;Node.js CommonJS 文件顶层通常是 module.exports;浏览器经典脚本顶层通常是全局对象。独立调用的严格性由函数自身代码决定,不由调用方决定。

箭头函数

  • 没有自己的 this 绑定
  • 常用于回调中保留外层 this
  • 不适合需要动态接收者的原型方法主路径

常见误区

[!warning] 常见误区:this 指向函数定义所在对象 普通函数看调用,不看定义位置。

工程实践

  • class 字段箭头:固定 this,但方法在实例上,注意内存。
  • 回调优先传 () => obj.method() 或 obj.method.bind(obj)。
  • React 事件里 class 组件历史绑定问题已被 hooks 函数组件弱化,但仍要理解。

本节总结

this 是调用约定,不是词法地址(箭头除外)。先判断怎么被叫,再读 this。

自测题

  1. 为什么 const f = obj.m; f() 危险?
  2. 箭头函数方法能被子类动态 this 复用吗?
参考答案
  1. 丢失隐式绑定,this 变默认绑定。
  2. 通常不能按“接收者对象”动态绑定;它捕获定义时外层 this。

延伸阅读

资料类型支撑内容
MDN this文档绑定规则
ECMA-262规范OrdinaryCallBindThis 等
创建于 2025/1/1 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本