JavaScript 事件对内存和性能的影响


Posted in Javascript onJanuary 22, 2017

虽说事件处理程序可以为现代 Web 页面添加很强的交互能力,但是不分青红皂白就添加大量的事件处理程序绝对是一种愚蠢的行为。

我们来分析一下:事件处理程序本质上是一种函数,是一种对象,存放在内存中,设置大量的事件处理程序会使内存中的对象变多,Web 程序的性能会变得越来越差,用户体验很不好。

为了更好地利用好事件处理程序,便出现了事件委托,用来提升性能。

事件委托

事件委托(event delegation):把若干个子节点上的相同事件的处理函数绑定到它的父节点上去,在父节点上统一处理从子节点冒泡上来的事件,这种技术就叫做事件委托。

补充一下:事件委托并不局限于父节点与子节点之间。也可以这样玩,比如页面文档中有好多个处在不同位置地 button,都是绑定 click 事件,使用事件委托,我们可以把这些个事件统一绑定到 body 元素,然后再进行处理(虽然一般很少这么用)。

下面举例子逐步说明事件委托的优势:

<ul id="parent-list">
 <li id="list-1">List 1</li>
 <li id="list-2">List 2</li>
 <li id="list-3">List 3</li>
 <li id="list-4">List 4</li>
 <li id="list-5">List 5</li>
</ul>

假设有上面的代码,我们现在有一个需求:就是无论单击上面的列表(ul)的哪个子列表(li),都会弹出一个框,来显示我们点击了哪个子列表。

需求不难吧?有了需求,接下来是该写 js 代码了,现在有两种方法放在你眼前:1. 为每个 li 子元素绑定 click 事件,然后设置处理函数; 2. 利用事件委托,为 ul 父元素绑定 click 事件,然后设置处理函数

// 方法一
var list1 = document.getElementById("list-1");
list1.addEventListener("click",function(){
 alert(this.firstChild.nodeValue);
},false);
var list2 = document.getElementById("list-2");
list2.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
var list3 = document.getElementById("list-3");
list3.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
var list4 = document.getElementById("list-4");
list4.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
var list5 = document.getElementById("list-5");
list5.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
// 方法二
var parentList = document.getElementById("parent-list");
parentList.addEventListener("click",function(){
 var target = event.target;
 if(target.nodeName.toLowerCase() === "li"){
 alert(target.firstChild.nodeValue);
 }
},false);

看着上面的代码,我这里写几点方法二的优点:1. 减少了访问 DOM 的次数,提升了性能;2. 将子元素的事件处理程序统一绑定到其父元素,减少了对内存的占用;3. 可以更好地管理事件处理程序,比如移除对某个事件处理程序的引用

注意:如果对各个子元素的需求不一样,我们还可以这样来改写上面的方法二:

// 方法二
var parentList = document.getElementById("parent-list");
parentList.addEventListener("click",function(){
 var target = event.target;
 if(target.nodeName.toLowerCase() === "li"){
 switch(target.id){
  case "list-1":
  alert("学的越多,越觉得自己无知!");
  break;
  case "list-2":
  alert("爱是一种艺术!");
  break;
  case "list-3":
  target.innerHTML = "呵呵,我改了啊!";
  break;
  case "list-4":
  target.style.background = "#aaa";
  break;
  case "list-5":
  target.style.color = "red";
  target.style.fontSize = "2em";
  break;
  default:
  break;
 }
 }
},false);

因为事件委托依赖事件冒泡机制,所以,并不是所有的事件都可以进行事件委托。

最适合采用事件委托的事件包括:click、mousedown、mouseup、keydown、keyup 和 keypress。

事件委托只是一种非常不错的事件绑定的思想,所以不应该拘泥于上面的例子,要活学活用! ^_^

移除事件处理程序

我们前面说过,事件处理程序存在于内存中,每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的 JavaScript 代码之间就会建立一个连接。这种连接越多,页面执行就越慢。前面所说的事件委托就是用来限制建立的连接数量。

还有,就是内存中那些使用完后不再使用的事件处理程序,如果不释放掉,也会影响 Web 应用程序的内存和性能。

<button id="button">提交</button>
var button = document.getElementById("button");
button.onclick = function(){
 // 提交某个表单的操作代码
 button.onclick = null; // 移除事件处理程序
 event.target.firstChild.nodeValue = "提交中。。。";
};

总的原则就是:移除掉那些过时不再使用的事件处理程序,释放内存!

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
getElementById在任意一款浏览器中都可以用吗的疑问回复
May 13 Javascript
利用jQuery的$.event.fix函数统一浏览器event事件处理
Dec 21 Javascript
javascript自定义函数参数传递为字符串格式
Jul 29 Javascript
jQuery文字提示与图片提示效果实现方法
Jul 04 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
Jul 15 Javascript
js 获取当前web应用的上下文路径实现方法
Aug 19 Javascript
Javascript实现前端简单的路由实例
Sep 11 Javascript
JS实现经典的中国地区三级联动下拉菜单功能实例【测试可用】
Jun 06 Javascript
JS设计模式之单例模式(一)
Sep 29 Javascript
JS模拟实现哈希表及应用详解
May 04 Javascript
vue中的适配px2rem示例代码
Nov 19 Javascript
JS实现轮播图效果
Jan 11 Javascript
Angular指令封装jQuery日期时间插件datetimepicker实现双向绑定示例
Jan 22 #Javascript
Bootstrap 下拉多选框插件Bootstrap Multiselect
Jan 22 #Javascript
JavaScript 详解预编译原理
Jan 22 #Javascript
JavaScript中匿名函数的递归调用
Jan 22 #Javascript
Javascript中字符串和数字的操作方法整理
Jan 22 #Javascript
loading动画特效小结
Jan 22 #Javascript
全面总结Javascript对数组对象的各种操作
Jan 22 #Javascript
You might like
简单采集了yahoo的一些数据
2007/02/14 PHP
thinkphp实现163、QQ邮箱收发邮件的方法
2015/12/18 PHP
[原创]解决wincache不支持64位PHP5.5/5.6的问题(提供64位wincache下载)
2016/06/22 PHP
PHP Oauth授权和本地加密实现方法
2016/08/12 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
jquery 插件之仿“卓越亚马逊”首页弹出菜单效果
2008/12/25 Javascript
Cookie 小记
2010/04/01 Javascript
用javascript删除当前行,添加行(示例代码)
2013/11/25 Javascript
js利用事件的阻止冒泡实现点击空白模态框的隐藏
2014/01/24 Javascript
jQuery之字体大小的设置方法
2014/02/27 Javascript
跟我学Nodejs(二)--- Node.js事件模块
2014/05/21 NodeJs
node.js中的path.dirname方法使用说明
2014/12/09 Javascript
jQuery解析XML与传统JavaScript方法的差别实例分析
2015/03/05 Javascript
JavaScript中String.match()方法的使用详解
2015/06/06 Javascript
基于jquery实现的树形菜单效果代码
2015/09/06 Javascript
JS字符串的切分用法实例
2016/02/22 Javascript
使用jQuery的ajax方法向服务器发出get和post请求的方法
2017/01/13 Javascript
bootstrap轮播图示例代码分享
2017/05/17 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
Angularjs单选框相关的示例代码
2017/08/17 Javascript
node.js调用C++函数的方法示例
2018/09/21 Javascript
基于JavaScript实现轮播图效果
2021/01/02 Javascript
[01:05:40]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第三场
2014/05/24 DOTA
用Python编写分析Python程序性能的工具的教程
2015/04/01 Python
简单讲解Python中的字符串与字符串的输入输出
2016/03/13 Python
高效测试用例组织算法pairwise之Python实现方法
2017/07/19 Python
python3 pillow模块实现简单验证码
2019/10/31 Python
Python中使用aiohttp模拟服务器出现错误问题及解决方法
2020/10/31 Python
校园公益广告语
2014/03/13 职场文书
酒店仓管员岗位职责
2014/04/28 职场文书
大学生见习报告总结
2014/11/04 职场文书
幼儿园2015年度工作总结
2015/04/01 职场文书
用人单位的规章制度,怎样制定才是有效的?
2019/07/09 职场文书
JavaScript函数柯里化
2021/11/07 Javascript
Spring Boot项目传参校验的最佳实践指南
2022/04/05 Java/Android
win11如何查看端口是否被占用? Win11查看端口是否占用的技巧
2022/04/05 数码科技