前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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.defaultPrevented 判断默认行为
浏览器事件系统

后续监听器怎样知道默认行为已经被取消?

在监听器里读 event.defaultPrevented,就能知道这次事件的默认行为是否已被成功取消。前提是事件可取消;对 cancelable: false 的事件调用 preventDefault() 不会把它变成已取消。

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

取消默认行为有明确状态

  1. cancelable事件是否允许取消默认行为
  2. preventDefault()请求取消默认行为
  3. defaultPrevented反映取消是否成功

被动监听器中调用 preventDefault() 不能正常取消默认行为。

核心回答

先记住这个答案

event.defaultPrevented 表示这次事件的默认行为是否已经被成功取消。前面的监听器调用 preventDefault() 后,后面的监听器可读取到 true,但只有 event.cancelable 为真且调用有效才成立。它不告诉你是谁取消的,也不代表事件传播停止;stopPropagation() 解决的是传播路径,职责不同。

  • defaultPrevented 是只读布尔值
  • preventDefault() 只对可取消事件有效
  • 它不表示传播已停止
  • 读取结果取决于监听器执行时机

嵌套组件尊重已处理的操作

父容器有统一菜单逻辑,子组件在某些情况下想阻止默认打开动作。父监听器可在自己执行时先看 defaultPrevented,避免重复处理已明确取消的行为。

读取取消状态JavaScript
const menu = document.querySelector('#menu')
menu.querySelector('[data-cancel-menu]').addEventListener('click', event => {
  event.preventDefault() // 子项先取消这次可取消的 click
})
menu.addEventListener('click', event => {
  if (event.defaultPrevented) return
  console.log('执行菜单动作', event.target.textContent)
})

点击带 data-cancel-menu 的子项时,事件先到达子项,再冒泡到菜单;父级因此读到 defaultPrevented === true。读取结果只反映此前已经执行的监听器。若另一个监听器稍后才调用 preventDefault(),当前回调不可能提前看到未来状态。 还要区分浏览器默认行为和业务回调。取消链接导航不会自动阻止其他 JavaScript 监听器执行,业务监听器是否退出,要自己检查状态或约定处理方式。

可取消、被动和传播

许多事件有默认行为可以取消,但不是所有事件都可取消。先检查 cancelable,再判断 defaultPrevented,能避免“我调用过 preventDefault(),怎么还是 false”的疑惑。被动监听器还不能有效取消默认行为。

stopPropagation() 只阻止事件继续传播,不会把 defaultPrevented 设为真;stopImmediatePropagation() 还会阻止同目标后续监听器,但仍与取消默认行为不同。

在多个组件共享一次点击时,defaultPrevented 可以作为“前面有人已经否决默认动作”的约定,但它不等于通用的“业务已处理”标志。子组件可能只阻止链接跳转,却仍希望父组件记录点击;父组件若一看到 true 就退出,埋点也会被跳过。具体哪些处理应退出,需要双方约定清楚。

监听器的执行次序也影响读取结果。子项的冒泡监听先于父项运行,所以父项能看到子项取消;父项的捕获监听在子项之前运行,那时还看不到后续取消。需要在父级统一兜底时,应把监听阶段算进设计。

回答前,多想一步

容易答错的地方

把 defaultPrevented 当成传播停止标志
停止传播不会自动取消默认行为,两者要分别判断。
在不可取消事件上调用 preventDefault() 就以为成功
cancelable: false 时不会产生期望的取消状态。
试着用自己的话回答

面试官还会怎么问?

怎样知道事件能否取消?

读取 event.cancelable。

调用 preventDefault() 会停止其他监听器吗?

不会。其他监听器仍可运行,除非另行控制传播或在回调里检查状态。

为什么滚动监听里取消无效?

可能注册了被动监听器,或该事件本身不可取消;要分别核查。

从一道题,走向一组知识

把知识连起来

事件系统

dispatchEvent 是同步的吗,监听器改 DOM 何时可见?

dispatchEvent() 的返回值也与可取消事件的默认行为是否被取消有关。

事件系统

Shadow DOM 里的事件,composed 和 composedPath 各回答什么?

跨 Shadow DOM 的事件路径影响哪些监听器能看到这个状态。

参考资料

  • MDN 参考文档

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

本题目录
  1. 先记住这个答案
  2. 嵌套组件尊重已处理的操作
  3. 可取消、被动和传播
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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