关注「松宝写代码」,精选好文,每日一题

作者:saucxs | songEagle

2020,实「鼠」不易

2021,「牛」转乾坤

风劲潮涌当扬帆,任重道远须奋蹄!

一、前言

2020.12.23 立的 flag,每日一题,题目类型不限制,涉及到JavaScript,Node,Vue,React,浏览器,http等领域。

本文是「每日一题」第 17 题:【每日一题】面试官问:JS中事件流,事件处理程序,事件对象的理解?

这是一道很宽泛的题目,如何回答更有亮点?

昨天的题目号码写错了,在这里做个说明?。

二、目录

  • 事件流

  • 事件处理程序

    • HTML事件处理程序

    • DOM0级事件处理程序

    • DOM2级事件处理程序

    • IE事件处理程序

    • 跨浏览器实现事件处理程序

  • 事件对象 Event

    • DOM中的事件对象

    • IE中的事件对象

    • 跨浏览器的事件对象

1、事件流

事件流描述的是从页面中接收事件的顺序。

事件冒泡流

IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。所有的现代浏览器都支持事件冒泡。

事件捕获流

Netscape Communicator团队提出的事件流叫做事件冒泡(event capturing),即事件开始时由不太具体的节点接收,而最具体的节点应该最后收到事件。

DOM2级事件

DOM2级事件规定事件流分为三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

2、事件处理程序

响应事件的函数称为事件处理程序。

HTML事件处理程序

在元素中使用事件处理程序,如:

id="btn" type="button" value="Button" onclick="alert(event.type)">

  • 使用该方式绑定的事件,在事件函数中存在一个局部变量 event,用来保存事件对象。

  • 该方式存在的缺点:

  • 1、JavaScript与HTML加载顺序的不确定性,可能在JavaScript未加载完成之前就触发相应的事件,产生错误。

  • 2、作用域连在不同的浏览器中会导致不同的结果。

  • 3、JavaScript与HTML代码的紧密耦合,如果需要更换事件处理程序,则需要更改两个地方。

DOM0级事件处理程序

第四代web浏览器中出现的方法,现在仍被个浏览器所支持。实现方式为将函数赋值给一个事件处理程序属性。

id="btn" type="button" value="Button">

let btn = document.getElementById('btn')

// 添加事件,多次定义后,最后一个将覆盖之前的定义

btn.onclick = function () {

alert(this.id)

}

// 删除事件

btn.onclick = null

使用该方式绑定的事件,在事件函数中可以使用 this访问元素的任何属性和方法,且在事件流的冒泡阶段被处理。

DOM2级事件处理程序

提供了两个方法 addEventListener()removeEventListener()分别用来指定和删除事件处理程序。所有的DOM节点都包含这两个方法。

接收三个参数:

  • 事件名

  • 事件处理程序的函数

  • 布尔值,默认值为false。 true: 在捕获阶段调用事件处理程序; false: 冒泡阶段调用事件处理程序

id="btn" type="button" value="Button">

let btn = document.getElementById('btn')

function fn ( ) {

alert('This is a function')

}

// 添加事件,可以定义多个,按照顺序执行

btn.addEventListener('click', function () {

alert('click1')

}, false)

btn.addEventListener('click', fn, false)

// 删除事件

btn.removeEventListener('click', fn)

  • 使用addEventListener添加的事件处理程序只能由removeEventListener删除,移除时与传入的三个参数必须完全相同。

  • removeEventListener无法移除匿名函数。

IE事件处理程序

与DOM2级类似,也提供了两个方法 attachEvent()detachEvent()分别用来指定和删除事件处理程序。所有的DOM节点都包含这两个方法。

使用attachEvent()添加的事件处理程序,均在冒泡阶段被处理。

接收两个参数:

  • 事件名

  • 事件处理程序的函数

id="btn" type="button" value="Button">

let btn = document.getElementById('btn')

function fn ( ) {

alert('This is a function')

}

// 添加事件,可以定义多个,按照相反的顺序执行

btn.attachEvent('onclick', function () {

alert('click1')

})

btn.attachEvent('onclick', fn)

// 删除事件

btn.detachEvent('onclick', fn)

与其他类型方法的区别

  • 1、主要区别是事件处理程序的作用域。在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中进行,this等于window。

  • 2、第一个参数必须是 on+事件名的形式。

  • 3、添加多个事件处理程序时,不是按照顺序依次执行,而是以相反的顺序执行。

跨浏览器实现事件处理程序

  • 创建一个EventUtil对象

  • 为EventUtil对象实现两个方法:addHandler()、removeHandler()

  • 主要是利用能力检测来实现

  • 以下示例的方法,还需要注意作用域的问题

let EventUtil = {

addHandler: function (el, type, handler) {

if (el.addEventListener) {

el.addEventListener(type, handler, false)

} else if (el.attachEvent) {

el.addHandler('on' + type, handler)

} else {

el['on' + type] = handler

}

},

removeHandler: function (el, type, handler) {

if (el.addEventListener) {

el.removeEventListener(type, handler, false)

} else if (el.attachEvent) {

el.detachEvent('on' + type, handler)

} else {

el['on' + type] = null

}

}

}

3、事件对象 Event

触发DOM事件时,会产生一个事件对象 event,这个对象包含着所有与事件相关的信息。包括导致事件的元素、事件类型以及其他与特定事件相关联的信息。

DOM中的事件对象

兼容DOM的浏览器会将 event对象传入到事件处理器中。触发的事件类型不一样,可以用的方法和属性也不一样。

所有的事件的event对象都包含以下属性和方法:

属性/方法 类型 读/写 说明
bubbles Boolean 只读 事件是否冒泡
cancelable Boolean 只读 是否可以取消事件的默认行为
currentTarget Element 只读 事件处理程序当前正在处理的元素
defaultPrevented Boolean 只读 为true时,表示已经调用了 preventDefault()
detail Integer 只读 与事件相关的细节信息
eventPhase Integer 只读 调用事件处理程序的阶段:1 捕获阶段;2:目标阶段;3:冒泡阶段
preventDefault Function 只读 取消事件的默认行为, cancelable===true时,可使用该方法
stopImmediatePropagation() Function 只读 取消事件的进一步捕获或者冒泡,同时阻止任何事件处理程序被调用
stopPropagation() Function 只读 取消事件的进一步捕获或者冒泡, bubbles===true时,可以使用该方法
target Element 只读 事件的目标
trusted Element 只读 true: 事件由浏览器生成;false:开发人员通过JS创建
type String 只读 事件的类型
view AbstractView 只读 与事件关联的抽象试图。等同于发生事件的window对象

说明

  • target 触发事件的真是目标

  • currentTarget 事件处理程序内部 this===currentTarget

  • 只有在事件处理程序执行期间,event对象才会存在;一旦事件处理程序执行完成,event对象就会被销毁。

IE中的事件对象

指定事件处理程序的方法不同,获取event对象的方式也不同。

  • DOM0级 使用 window.event获取event对象

  • 使用 attachEvent()方式添加,会有一个event对象作为参数被传入事件处理程序,当然在这种情况下,也可以通过window对象来获取event对象。

所有的事件的event对象都包含以下属性和方法:

属性/方法 类型 读/写 说明
cancelBubbles Boolean 读/写 默认false,true:可以取消事件冒泡,与DOM中的 stopPropagation()方法相同
returnValue Boolean 读/写 默认true,false:取消事件的默认行为,与DOM中的 preventDefault()方法相同
srcElement Element 只读 事件的目标,与DOM中的 target属性相同
type String 只读 事件的类型

说明

  • 因为事件处理程序的作用域是根据指定它的方式来确定的,所以最好使用 srcElement来确定事件目标。

跨浏览器的事件对象

针对IE与DOM事件的差异,可以继续补充前面创建的 EventUtil对象,解决兼容性问题。

let EventUtil = {

addHandler: function (el, type, handler) {

if (el.addEventListener) {

el.addEventListener(type, handler, false)

} else if (el.attachEvent) {

el.addHandler('on' + type, handler)

} else {

el['on' + type] = handler

}

},

removeHandler: function (el, type, handler) {

if (el.addEventListener) {

el.removeEventListener(type, handler, false)

} else if (el.attachEvent) {

el.detachEvent('on' + type, handler)

} else {

el['on' + type] = null

}

},

// ------- 新增加的关于事件对象的兼容性处理 --------

getEvent: function (event) {

return event ? event : window.event

},

getTarget: function (event) {

return event.target || event.srcElement

},

preventDefault: function (event) {

// 阻止事件的默认行为

if (event.preventDefault) {

event.preventDefault()

} else {

event.returnValue = true

}

},

stopPropagation: function (event) {

// 阻止冒泡

if (event.stopPropagation) {

event.stopPropagation()

} else {

event.cancelBubbles = true

}

}

}

谢谢支持

1、喜欢的话可以「分享,点赞,在看」三连哦。

2、作者昵称:saucxs,songEagle,松宝写代码。「松宝写代码」公众号作者,每日一题,实验室等。一个爱好折腾,致力于全栈,正在努力成长的字节跳动工程师,星辰大海,未来可期。内推字节跳动各个部门各个岗位。

3、长按下面图片,关注「松宝写代码」,是获取开发知识体系构建,精选文章,项目实战,实验室,每日一道面试题,进阶学习,思考职业发展,涉及到JavaScript,Node,Vue,React,浏览器,http等领域,希望可以帮助到你,我们一起成长~

字节内推福利

  • 回复「校招」获取内推码

  • 回复「社招」获取内推

  • 回复「实习生」获取内推

后续会有更多福利

学习资料福利

回复「算法」获取算法学习资料

往期「每日一题」

1、JavaScript && ES6

  • 第 16 题:【每日一题】面试官问:JS中如何全面进行客户端检测?

  • 第 15 题:【每日一题】面试官问:JS类型判断有哪几种方法?

  • 第 14 题:【每日一题】面试官问:谈谈你对JS对象的创建和引申

  • 第 13 题[每日一题]面试官问:['1', '2', '3'].map(parseInt)输出,原因,以及延伸?

  • 第 12 题[每日一题]面试官问:JS引擎的执行过程(二)

  • 第 11 题[每日一题]面试官问:JS引擎的执行过程(一)

  • 第 10 题[每日一题]面试官问:详细说一下JS数据类型

  • 第 8 题[每日一题]面试官问:谈谈你对ES6的proxy的理解?

  • 第 7 题[每日一题]面试官问:for in和for of 的区别和原理?

  • 第 6 题[每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?

  • 第 3 道「「每日一题」面试官问你对 Promise 的理解?可能是需要你能手动实现各个特性」

  • 第 2 道「[每日一题]ES6 中为什么要使用 Symbol?」

2、浏览器

  • 第 9 题[每日一题]requestAnimationFrame不香吗?

3、Vue

  • 第 5 道「每日一题」到底该如何回答:vue数据绑定的实现原理?

4、算法

  • 第 4 道「每日一题」与面试官手撕代码:如何科学高效的寻找重复元素?

5、Http

  • 第 1 道「一道面试题是如何引发深层次的灵魂拷问?」

后处理程序文件大小的变量_【每日一题】(17题)面试官问:JS中事件流,事件处理程序,事件对象的理解?...相关推荐

  1. 艾为数字ic面试题_每日学习:数字后端面试100问(2019全新版)

    关注并标星大同学吧 每天1次,打卡学习 积累1个新知识,增1分职场底气 作者称谓:Tao涛 个人介绍:摸爬滚打多年的数字后端工程师 微信公众号:数字后端IC芯片设计 半导体知识分享第29期 技能升级, ...

  2. 解决方案和项目的区别_(实习招聘)PwC面试官问Advisory和Consulting有什么区别,怎么答?...

    点击添加图片描述(最多60个字) Advisory VS Consulting 一直是困扰职场小白的两个单词 明明中文都翻译为"咨询" 为什么它们偏偏是两个不同的部门? 想进入咨询 ...

  3. java执行sql文件_面试官问你MyBatis SQL是如何执行的?把这篇文章甩给他

    初识 MyBatis MyBatis 是第一个支持自定义 SQL.存储过程和高级映射的类持久框架.MyBatis 消除了大部分 JDBC 的样板代码.手动设置参数以及检索结果.MyBatis 能够支持 ...

  4. obj: object是什么意思_面试官问你JavaScript基本类型时他想知道什么?

    本文原载于SegmentFault专栏"前端小将" 整理编辑:SegmentFault 面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括: 1.基本类型(值类 ...

  5. eureka自我保护时间_阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默...

    文章首发:阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默 什么是服务注册? 首先我们来了解下,服务注册.服务发现和服务注册中心的之间的关系. 举个形象的例子,三者之间的关系就好像是供货 ...

  6. js var是什么类型_面试官问你JS基本类型时他想知道什么?

    点击上方"IT平头哥联盟",选择"置顶或者星标" 一起进步- 面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括: 1.基本类型(值类型或者 ...

  7. 面试官问你想找什么工作_找工作时如何面试面试官

    面试官问你想找什么工作 在技​​术面试中要问的十二个问题 (Twelve questions to ask at tech interviews) I've just come off six wee ...

  8. 存在就不插入_动画:面试官问我插入排序和冒泡排序哪个更牛逼?

    来自公众号:小鹿动画学编程 写在前边 排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的插入排序.还有一些其他经典的排序,小鹿整理的共有 ...

  9. .jar中没有主清单属性_面试官问:为什么SpringBoot的 jar 可以直接运行?

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 来源 | https://urlify.cn/uQvIna SpringBoot提供了一个插件spring-boot-mav ...

最新文章

  1. 【MySQL】Got fatal error 1236原因和解决方法
  2. 无法分配更多的internet句柄怎么回事_一文精通Java NIO(内容较多,无耐心者勿点)...
  3. 如何在 IntelliJ IDEA 中整合 Maven、Tomcat 部署 Web 应用
  4. 64位系統修復dll
  5. 吃PHP小孩智力好,这7种鱼千万不能给孩子吃,会影响孩子的智力!
  6. java快捷键禁用_pycharm 掌握这些快捷键,你就是大神!!
  7. Android 圆角TabLayout
  8. 罗永浩直播公司回应被列入经营异常:更换了地址 一切正常
  9. stata基本操作(二)
  10. TortoiseSVN中的“文件和文件夹过滤”在VS项目中的使用
  11. 使用C#和Excel进行报表开发(三)-生成统计图(Chart)
  12. SpringBoot番外篇-微服务架构【1.起源与定义】
  13. HIBERNATE调试工具JBOSS TOOLS
  14. mysql 中文脱敏_怎样选择数据库脱敏系统?
  15. AutoCAD二次开发——引线标注
  16. 11:c# oop思想面向对象编程(by-朝夕)
  17. AS更换背景主题以及背景图片
  18. 【踩坑记录】priority_queue 第三个模板参数和sort 的第三个形参的区别;仿函数、自定义排序函数、lambda 函数分别传入;传入类型和对象的区别;
  19. 2018手机江湖之战:OPPO的变与不变
  20. 使用跳板机在Pycharm上配置内网服务器

热门文章

  1. CPU状态信息us,sy,ni,id,wa,hi,si,st含义
  2. 大数据在犯罪预防中有独特价值
  3. java中的NAN和INFINITY
  4. OkHttp源码分析
  5. atitit.mp4 视频文件多媒体格式结构详解
  6. [LeetCode]Merge Sorted Array
  7. phpMyAdmin FTP iptables Selinux
  8. linux 学习笔记 (1) —— 安装 Redhat enterprise 5
  9. 开发板运行linux下虚拟机ubuntu的ping
  10. 硬件基础:电阻作用及产品应用