this 关键字

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

#type / concept #status / growing #tech / dev #resource / javascript #resource / ecmascript

[!info] 关联笔记

this 关键字

这个概念为什么出现

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

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

最小可运行示例

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

const inventoryService = {
  warehouse: 'A仓',
  label(sku) {
    // 业务意图:打印仓库前缀;教学点:谁调用,this 就指向谁
    return this.warehouse + '::' + sku
  },
}

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

const detached = inventoryService.label
try {
  // 严格模式 / 模块顶层下常为 TypeError 或无法读 warehouse
  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
  },
}

建议运行:

node --input-type=module -e "/* 粘贴为模块可观察严格 this */"
# 或把文件存为 mjs/cjs 分别观察

结合场景关注点

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

核心规则(普通函数)

调用形式this 直觉
fn()undefined(严格)/ 全局对象(非严格、非模块)
obj.fn()obj
fn.call(x) / apply / bind显式为 x
new Fn()新创建的实例
DOM 事件处理器(历史)监听元素(注意框架封装差异)

优先级教学口诀:new > 显式 > 隐式 > 默认(细节与 bound function 组合以规范为准)。

箭头函数

  • 没有自己的 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/7/15