JavaScript不仅门槛低,而且是一门有趣、功能强大和非常重要的语言。各行各业的人发现自己最混乱的选择是JavaSscript编程语言。由于有着各种各样的背景,所以不是每个人都对JavaScript及其基本原理有广泛的认识。通常来书,除非你去参加工作面试才会去思考为什么或者怎么做,否则JavaScript只是你工作的内容。

这个系类的目标是深入探讨JavaScript的一些概念和理论。主题来自于 Darcy Clarke的JavaScript典型面试问题列表。希望你不仅仅是为了答案而阅读完这篇文章,每一篇文章会让对过去学过的知识有一个新的理解,或者重温你学习的东西,这有利于你用JavaScript实现所有交互。

详解事件委托

事件委托是一种由其它元素而非事件目标元素来响应事件产生的行为的思想。用document元素来处理按钮的点击行为就是事件委托的一个例子,另一种常见情况是,用ul元素来处理其子元素li的事件。

有多种方法来处理事件委托。标准方法来源于原生浏览器的功能。浏览器以一种特定的工作流程来处理事件,并支持事件捕获和事件冒泡。W3C关于浏览器怎么支持事件的文档:W3C DOM Level 3 Events。一些JS库和框架公开了其它方式,如发布/订阅模型(将在后文提及)。

事件捕获和事件冒泡是事件流中的两个阶段,任何事件产生时,如点击一个按钮,将从最顶端的容器开始(一般是html的根节点)。浏览器会向下遍历DOM树直到找到触发事件的元素,一旦浏览器找到该元素,事件流就进入事件目标阶段,该阶段完成后,浏览器会沿DOM树向上冒泡直到最顶层容器,看看是否有其它元素需要使用同一个事件。

下面的示例说明了这个过程。点击按钮会导致事件流识别本身在容器下面的文本,每一个元素都接收同样的点击监听代码,由于事件捕获,点击事件会首先触发HTML节点绑定的点击处理程序,然后在事件冒泡阶段的末尾返回到最顶层元素。

View this on JSFiddle

大多数现代库使用冒泡监听,而在捕获阶段处理。浏览器包含一个方法来管理事件冒泡。事件处理程序可以调用stopPropagation告诉DOM事件停止冒泡,第二个方式是调用stopImmediatePropagation,它不仅停止冒泡,也会阻止这个元素上其它监听当前事件的处理程序触发。然而,停止传播事件时要小心,因为你不知道是否有其它上层的DOM元素可能需要知道当前事件。

还有第三个可以控制元素如何对事件作出回应的方法。所有现代浏览器支持preventDefault方法,这个方法会阻止浏览器处理事件的默认行为。一个常见示例就是链接,使用链接执行UI操作是一种常见的做法。然而,当我们不希望链接跟普通被激活的链接一样会在新标签页打开一个新页面,就可以使用preventDefault方法来阻止这个默认行为。

还有其它实现事件委托的方法可以考虑,其中值得一提的就是发布/订阅模型。发布/订阅模型也称为了广播模型,牵涉到两个参与者。通常,两个参与者在DOM中并没有紧密的联系,而且可能是来自兄弟的容器。可以给它们共同的祖先元素设置监听处理程序,但是如果共同的祖先元素在DOM树中处于较高层次(离根节点比较近),就会监听很多同辈元素的事件,会造成意想不到的结果;当然,也可能存在逻辑或结构原因要分开这两个元素。

发布/订阅模型也能自定义事件。发布/订阅模型从一个元素发送消息后并向上遍历,有时也向下遍历,DOM会通知遍历路径上的所有元素事件发生了。在下面的示例中,JQuery通过trigger方法传递事件。

View this on JSFiddle

使用事件委托来管理事件流有很多优点,其中最大的优点是改善性能。元素绑定的每一个监听器都会占用一些内存,如果页面上只有少数几个监听器,我们也不会注意到它们之间的区别,然后,如果要监听一个50行5列的表格中的每个单元格,你的Web应用会开始变慢,为了使应用程序最快运行的最好方式是保持尽可能低的内存使用。

使用事件委托能减少监听器数量,在元素的容器上绑定事件意味着只需要一个监听器。这种方法的缺点是,父容器的侦听器可能需要检查事件来选择正确的操作,而元素本身不会是一个监听器。额外处理带来的影响远低于许多存在内存中的监听器。

更少的监听器和更少的DOM交互也易于维护。父容器层次的监听器能处理多种不同的事件操作,这是一种简单的方法来管理相关的事件操作,这些事件通常需要执行相关功能或需要共享数据。

如果父容器是监听器,然后要执行独立的内部操作而并不需要添加或者移除本身的监听器。元素操作在单页应用中是极其常见的,为某部分添加一个按钮这样简单的事情也会为应用程序创建一个潜在的性能块,没有合适的事件委托,就必须手动为每一个按钮添加监听,如果每个侦听器不清理干净,它可能会导致内存泄漏。浏览器不会清理页面,因此在单页应用中,所有从内存中清理不当的碎片都会留在内存中,这些碎片会降低程序性能。

当在页面中添加交互时,仔细考虑一下,是否真的需要去监听元素。

另一篇值得一读的文章:Event Delegation In JavaScript

this在JavaScript中是怎么工作的

this 关键字在JavaScript中的一种常用方法是指代码当前上下文。

  • 如果this没有被设置,则默认指向全局对象,其通常是window
  • 如果一个函数中运行了一个内联函数,比如一个事件监听器,则this指向内联函数的源代码。例如,当设置一个按钮的单击处理程序,this将引用匿名函数内的按钮。
  • 如果函数是一个对象的构造函数,this指向新对象。
  • 如果函数被定义在一个对象上,然后调用对象时,this指向该对象。

在异步编程中,this可以很容易改变过程中一个功能操作。保持处理程序上下文的一个小技巧是将其设置到闭包内的一个变量,当在上下文改变的地方调用一个函数时,如setTimeout,你仍然可以通过该变量引用需要的对象。

操作this的另一种方式是通过callapplybind。三种方法都被用于调用一个函数,并能指定this的上下文,你可以让代码使用你规定的对象,而不是依靠浏览器去计算出this指向什么。Callapplybind本身是相当复杂的,应该有自己的文档记录,我们会把这当做未来待解决问题的一部分。下面是一个改变this指向方法的示例:

View this on JSFiddle

事件委托和this是现代JavaScript中重要的功能,理解它们的工作原理是成功开发产品的关键,并且可以肯定的是,这是应聘JavaScript工程师必须要了解的。

译文出处:http://www.ido321.com/1570.html

本文根据@Nicolas Bevacqua的《JavaScript Interview Questions: Event Delegation and This》所译,整个译文带有我自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://modernweb.com/2014/11/25/javascript-interview-questions-event-d...

【译】JavaScript面试问题:事件委托和this相关推荐

  1. javascript举例介绍事件委托的典型使用场景

    在了解什么是DOM事件以及给DOM事件绑定监听器的几种方法后,我们来谈谈事件委托. 1. e.target 和 e.currentTarget 当我们给目标元素target 绑定一个事件监听器targ ...

  2. JavaScript:事件冒泡和事件委托

    2019独角兽企业重金招聘Python工程师标准>>> JavaScript事件代理和委托(Delegation) JavaScript事件冒泡和事件委托 JavaScript:通过 ...

  3. Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制

    一.事件的捕获与冒泡 由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监 ...

  4. 事件绑定、事件监听、事件委托

    2019独角兽企业重金招聘Python工程师标准>>> 在JavaScript的学习中,我们经常会遇到JavaScript的事件机制,例如,事件绑定.事件监听.事件委托(事件代理)等 ...

  5. 5选项卡(封装插件版)加事件委托版选项卡

    HTML代码(两款HTML选项卡代码): 第一款:非事件委托版HTML代码: <!DOCTYPE html> <html> <head><meta chars ...

  6. JavaScript面试问题:事件委托和this

    JavaScript不仅门槛低,而且是一门有趣.功能强大和非常重要的语言.各行各业的人发现自己最混乱的选择是JavaSscript编程语言.由于有着各种各样的背景,所以不是每个人都对JavaScrip ...

  7. “约见”面试官系列之常见面试题之第六十六篇之事件委托的原理和实现(建议收藏)

    事件委托(事件代理)原理:简单的说就是将事件交由别人来执行,就是将子元素的事件通过冒泡的形式交由父元素来执行. 为什么要用时间委托? 在JavaScript中,添加到页面上的事件处理程序数量将直接关系 ...

  8. javascript和jq的事件委托

    2019独角兽企业重金招聘Python工程师标准>>> 今天在公司,有个需求是,通过ajax动态查询数据,回来,再添加到一个ul的li元素中,例如(点击生成 li 模拟,加载数据生成 ...

  9. Javascript事件委托

    概念: 事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. 事件冒泡:就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul ...

最新文章

  1. 默的各种写法图片_SEO标题写法?
  2. 魅族的android m l,Android M 外部存储剖析
  3. POJ 1679 判断最小树是否唯一
  4. 神武服务器维护打副本,6月9日神武2维护解读:120级副本奖励次数提升
  5. python数据科学导论 中南_Python数据科学导论
  6. docker安装gitlab_Gitlab 中 CI/CD 自动化部署与使用
  7. gcc/g++编译器的优化
  8. maven中的snapshot来源与注意事项
  9. 计蒜客挑战难题:整数转换成罗马数字
  10. 基于JAVA+Servlet+JSP+MYSQL的图书馆座位预约系统
  11. CentOS 7.x 安装教程、硬盘分区、LVM、网络配置、软件源配置、制作USB Disk、U盘安装、网络安装...
  12. html表单实例:用户反馈表单页面代码
  13. 动态逆序对:CDQ分治
  14. 怎么查看微信收藏功能的剩余可用空间
  15. 精简指令集(RISC)和复杂指令集(CISC)的区别
  16. 2D坐标系与3D坐标系的相互转换--python实现
  17. 2023年还在问前端怎么学?一份前端学习指南
  18. 简谈计算机网络与网络编程
  19. Android开发——菜单(Menu)-——上下文菜单(ContextMenu)、 弹出菜单(PopupMenu)
  20. javaweb超市管理系统--用户管理

热门文章

  1. 如何打印网页版的发票_纸质发票将消失,电子发票如何报销、打印、收集?这一篇就够了...
  2. python cv.rectangle_Python OpenCV cv2.rectangle()用法及代码示例
  3. 利用ambassador实现container跨主机连接
  4. configure 包,出现error: no acceptable C compiler found in $PATH 问题
  5. epoll、mysql概念及简单操作
  6. python之路---15 装饰器
  7. C4-Squid-Purge
  8. 人工智能,大数据,云计算大杂烩
  9. 【转载】Java中String类的方法及说明
  10. iOS边练边学--UITableViewCell的常见属性设置