ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

现代 JavaScript 教程实战:哪个事件处理程序会运行——addEventListener、removeEventListener 与 onclick 的共存与差异解析

现代 JavaScript 教程实战:哪个事件处理程序会运行——addEventListener、removeEventListener 与 onclick 的共存与差异解析 文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载导读本文围绕《现代 JavaScript 教程zh.javascript.info》浏览器事件简介章节中的经典自测题展开当同一个按钮上同时存在addEventListener、removeEventListener与onclick赋值时点击后究竟哪些处理程序会运行、弹出哪些 alert。读完本文你将彻底掌握事件处理程序的三种绑定方式各自的语义、removeEventListener移除失效的根本原因函数对象同一性以及在实际项目中正确管理事件监听器的方法。原题重现哪个处理程序会运行仓库中 task.md 给出的题目如下原题重要程度标记为 5属于核心必会题在变量中有一个按钮。它上面没有处理程序。执行以下代码之后哪些处理程序会在按钮被点击时运行会显示哪些 alertbutton.addEventListener(click, () alert(1)); button.removeEventListener(click, () alert(1)); button.onclick () alert(2);答案1和2都会显示根据仓库中的官方解答 solution.md答案明确为1和2。即点击按钮后会依次弹出两次 alert内容分别是1和2。逐行解析为什么 removeEventListener 没有删掉第一个监听器第一行注册匿名监听器button.addEventListener(click, () alert(1));这一行向按钮注册了一个click事件监听器。注意它传入的是一个匿名箭头函数——这个函数对象在代码执行到这一行时被即时创建且没有保存到任何变量中。第二行试图移除——但传入了另一个函数button.removeEventListener(click, () alert(1));问题就出在这里。removeEventListener要成功移除一个监听器必须传入与注册时完全相同的函数对象。而这行代码又创建了一个新的匿名箭头函数——尽管它的函数体看起来一模一样同样是alert(1)但它是一个全新的函数对象与第一行注册的那个不是同一个引用。因此第一行注册的监听器没有被移除它仍然挂在按钮上点击时照常触发弹出1。这是 article.md 中明确强调的规则要移除处理程序我们需要传入与分配的函数完全相同的函数。removeEventListener获取了另一个函数——使用相同的代码但这并不起作用因为它是一个不同的函数对象。第三行DOM 属性赋值独立生效button.onclick () alert(2);button.onclick属于DOM 属性property方式的处理程序与addEventListener机制是两套独立的体系。即使没有任何addEventListener调用这条赋值也会让按钮在被点击时执行alert(2)。官方解答的最后一句点明了结论无论addEventListener怎样button.onclick处理程序都会触发。汇总点击按钮时的完整行为代码是否生效点击后的效果addEventListener(click, () alert(1))生效未成功移除弹出1removeEventListener(click, () alert(1))无效函数对象不同无效果button.onclick () alert(2)生效弹出2点击按钮后两个监听器都会运行分别弹出1和2。从 article.md 可知DOM 属性与addEventListener可以同时使用来设置处理程序两者互不覆盖。核心原理函数对象同一性与无法读回的监听器为什么长得一样不算同一个在 JavaScript 中函数是对象。每次执行() alert(1)这个表达式都会在内存中创建一个全新的函数对象即使函数体完全相同。比较两个函数对象是否相等比较的是引用内存地址而不是源码文本。所以// ❌ 移除失败两个箭头函数是两个不同的对象 elem.addEventListener(click, () alert(Thanks!)); elem.removeEventListener(click, () alert(Thanks!)); // ✅ 移除成功同一个函数对象 function handler() { alert(Thanks!); } elem.addEventListener(click, handler); elem.removeEventListener(click, handler);由 addEventListener 分配的处理程序无法被读回还有一个必须牢记的事实同样出自 article.md 的警告框如果我们不将函数存储在一个变量中那么我们就无法移除它。由addEventListener分配的处理程序将无法被读回。也就是说不存在element.getEventListeners()这类 API 能把已注册的监听器取出来再传给removeEventListener。唯一的正确做法是一开始就把处理函数保存成变量/具名函数注册与移除时都引用同一个对象。实战修正正确编写可移除的监听器回到原题如果我们的意图是注册后立刻移除避免重复监听正确的写法应当是把函数存起来// 存储对函数的引用 function handler() { alert(1); } button.addEventListener(click, handler); button.removeEventListener(click, handler); // 现在可以成功移除了 button.onclick () alert(2);这样第一个监听器被正确移除点击按钮后只会弹出2——这正是removeEventListener存在的意义避免在多次注册后产生重复执行。addEventListener/removeEventListener的完整语法见 article.mdelement.addEventListener(event, handler[, options]); element.removeEventListener(event, handler[, options]);event事件名例如clickhandler处理程序函数或具有handleEvent方法的对象options可选对象常见属性包括once: true——触发一次后自动删除监听器capture——指定事件处理的阶段由于历史原因options也可直接传false/true等价于{capture: false/true}passive: true——声明处理程序不会调用preventDefault()。延伸对比事件处理程序的三种绑定方式本题背后考察的其实是三种绑定方式的差异系统梳理如下源自 article.md1. HTML 特性attributeonclick...input valueClick me onclickalert(Click!) typebutton浏览器读取特性内容后会根据特性中的代码创建一个新函数并写入对应的 DOM 属性因此它与方式 2 本质相同。特性名大小写不敏感ONCLICK、onClick均可但惯例用小写。此方式不适合承载大量代码。2. DOM 属性propertyelem.onclick functionelem.onclick function() { alert(Thank you); };关键限制一个事件只能有一个 DOM 属性处理程序新赋值会覆盖旧值要移除只需elem.onclick null。注意 DOM 属性是大小写敏感的写elem.onclick而非elem.ONCLICK且不要使用setAttribute(onclick, ...)因为特性只能是字符串函数会被转成字符串而失效。3. 方法methodaddEventListener/removeEventListenerelem.addEventListener(click, handler1); // 可以注册多个 elem.addEventListener(click, handler2);这是最灵活的方式允许为一个事件注册多个处理程序不会相互覆盖还能以对象作为处理程序事件发生时调用对象的handleEvent(event)方法并且少数事件如DOMContentLoaded、transitionend只能通过它来注册。它的唯一代价是写法较长以及必须遵守移除需同一函数对象的规则。小结与自查清单回到原题答案是1和2都会被弹出。请确保你掌握了以下四个要点这也是本章 article.md 的考核核心removeEventListener必须传入与注册时完全相同的函数对象匿名函数无法被移除处理程序一旦由addEventListener注册就无法被读回必须事先存好引用DOM 属性onclick与addEventListener是两套并存机制彼此不覆盖一个事件可以通过addEventListener绑定多个处理程序而 DOM 属性只能有一个。实战中凡是涉及注册→后续可能要移除的场景例如轮播组件、懒加载监听、防重复绑定请一律采用具名函数 变量引用的写法避免踩中本题所展示的移除失效陷阱。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐现代 JavaScript 教程哪个处理程序会运行——深入剖析 removeEventListener 的函数引用与 onclick 共存机制现代 JavaScript 教程哪个处理程序会运行——深入剖析 removeEventListener 的函数引用与 onclick 共存机制 本文基于《现文档教程前端现代 JavaScript 教程使用 onclick 与 this.hidden 实现按钮点击自隐藏现代 JavaScript 教程使用 onclick 与 this.hidden 实现按钮点击自隐藏 本篇文章围绕现代 JavaScript 教程Moder文档/教程前端JavaScript 运行时原理事件循环、调用栈与内存管理实战解析JavaScript 运行时原理事件循环、调用栈与内存管理实战解析 本篇技术指南深度剖析 JavaScript 运行时Runtime的核心机制——事件循环教程文档上一篇Mono Profiled AOT.NET 运行时中基于 Profile 引导的 Mono 预编译方案下一篇LeetCode 与 GPT 系列教程Sigmoid 与 ReLU 激活函数从公式推导到 NumPy 向量化实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表