前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库事件对象派发 生命周期 复用
浏览器事件系统

浏览器会把上一次的 Event 对象复用给下一次点击吗?

同一次派发沿传播路径运行的监听器共享那次 Event 对象;下一次真实用户操作是另一次事件,不能假定浏览器复用同一个对象。脚本可保存并在上次派发结束后再次派发自建事件,但不应把它当成新事件快照。

前端进阶之旅 · 一题精讲更新于 2026.09.29
浏览器#事件系统#事件循环
先看核心答案读代码示例
理解线索

事件对象有派发时上下文

  1. Event 对象承载一次派发的属性与状态
  2. currentTarget当前正在运行监听器的目标
  3. dispatchEvent()允许派发自建事件但限制重入

异步回调里再读 event.currentTarget 常得到 null,应在同步监听器里先保存需要的引用。

核心回答

先记住这个答案

一次事件从按钮传播到父容器时,各监听器拿到的是同一次派发的事件对象,只是 currentTarget 随当前监听器变化。下一次用户点击应当作为新的事件处理,不能把上次事件对象当成会自动更新的容器。脚本创建的 Event 可以保存,在前一次派发完成后再次 dispatchEvent();但在它尚在派发时重入会报错,而且旧的取消状态等信息可能造成困惑,通常每次操作新建对象更清楚。

  • 同一次传播共享同一事件对象
  • 独立用户操作是不同事件
  • currentTarget 只在回调期间有意义
  • 自建事件不能在派发中重入派发

异步读取 currentTarget 的坑

列表点击时准备稍后上报“哪个容器处理了事件”。若把整个 event 留到 Promise 回调里再读 currentTarget,派发已经结束,它通常是 null。需要的节点和 ID 应在同步监听器里先取出。

先保存业务数据JavaScript
const list = document.querySelector('#items')
list.addEventListener('click', event => {
  const container = event.currentTarget // 监听器执行期间读取
  const id = event.target.closest('[data-id]')?.dataset.id
  queueMicrotask(() => {
    console.log({ id, containerId: container.id })
  })
})

微任务里用的是已经保存的 container 和 id,不依赖事件派发结束后的动态上下文。event.target 可能仍可访问,但目标节点也可能随后被删除,保存稳定业务 ID 更可靠。 同一次传播里,父子监听器看到的 currentTarget 不同。不能把它当成事件最初发生的位置;原始目标看 target,跨 Shadow DOM 时还要考虑重定向。

自建事件对象可以再次派发,但别滥用

脚本可创建一个 Event 后先派发到 A,再在前一次派发结束后派发到 B。第二次派发不是“浏览器复用用户点击对象”,而是你的代码主动把同一个对象再次交给事件系统。

DOM 规范禁止同一对象在派发尚未结束时再次派发。即使顺序派发允许,事件上的状态与引用仍可能让业务逻辑难懂;通常每次业务动作创建一个新事件对象。框架的合成事件还可能有自己的包装规则,不应混同于原生 DOM 事件。

例如一个可取消的自建事件第一次派发时被监听器调用了 preventDefault(),之后复用同一个对象再派发,已有取消状态可能影响第二次的判断。与其手动重置并猜测哪些状态会保留,不如用相同参数新建 Event;事件对象本身只负责描述这一回发生的事,业务数据另存。

在异步逻辑里保留事件引用也不是绝对错误,但应只读取稳定且确实需要的字段。currentTarget 是派发期间的上下文,派发结束就不适合再读;目标元素虽然还能引用,却可能已经离开文档。把 id、坐标和必要状态复制到普通对象里更容易复核。

回答前,多想一步

容易答错的地方

认为事件对象一过回调就不能保存
对象引用仍可保存,但 currentTarget 等派发时上下文不保证在回调外仍有值。
认为两个连续真实点击必定共享一个对象
每次独立用户操作应按独立事件处理,不能依赖对象身份复用。
试着用自己的话回答

面试官还会怎么问?

异步上报最应该提前保存什么?

保存业务 ID、必要坐标及当前监听容器等稳定数据,别在异步回调里重新读 currentTarget。

能在自己的监听器里再次派发同一个事件吗?

不能在该对象仍处于派发中时重入;会触发状态错误。

React 的合成事件与原生事件一样吗?

它是框架层包装,映射和生命周期可能不同;这里讨论的是原生 DOM Event。

从一道题,走向一组知识

把知识连起来

事件系统

addEventListener 的 signal 选项如何帮助自动移除监听器?实现 AB 测试或一次性订阅时有用吗?

异步清理前应在回调内保存业务 ID;signal 只负责移除监听器,不保留事件对象的 currentTarget。

事件系统

focus 和 blur 事件不冒泡,为何仍能通过事件委托实现,但必须使用捕获?

捕获 focus 时父子监听器接收同一次派发的事件对象,但各自的 currentTarget 不同。

参考资料

  • MDN 参考文档

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 异步读取 currentTarget 的坑
  3. 自建事件对象可以再次派发,但别滥用
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑