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 相关文章推荐
关于jquery append() html时的小问题的解决方法
Dec 16 Javascript
S2SH整合JQuery+Ajax实现登录验证功能实现代码
Jan 30 Javascript
JavaScript学习笔记之Function对象
Jan 22 Javascript
浅谈Javascript 数组与字典
Jan 29 Javascript
基于javascript实现页面加载loading效果
Sep 15 Javascript
最常见的左侧分类菜单栏jQuery实现代码
Nov 28 Javascript
浅谈关于angularJs中使用$.ajax的注意点
Aug 12 Javascript
vue-cli脚手架build目录下utils.js工具配置文件详解
Sep 14 Javascript
js 根据对象数组中的属性进行排序实现代码
Sep 12 Javascript
Vue解析剪切板图片并实现发送功能
Feb 04 Javascript
js实现简单点赞操作
Mar 17 Javascript
Vue基本指令实例图文讲解
Feb 25 Vue.js
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
php调用方法mssql_fetch_row、mssql_fetch_array、mssql_fetch_assoc和mssql_fetch_objcect读取数据的区别
2012/08/08 PHP
PHP使用适合阅读的格式显示文件大小的方法
2015/03/05 PHP
PHP+Mysql+jQuery实现发布微博程序 php篇
2015/10/15 PHP
在 Laravel 中动态隐藏 API 字段的方法
2019/10/25 PHP
基于Jquery与WebMethod投票功能实现代码
2011/01/19 Javascript
javascript实现的DES加密示例
2013/10/30 Javascript
js判断浏览器类型为ie6时不执行
2014/06/15 Javascript
JavaScript中的操作符==与===介绍
2014/12/31 Javascript
简介JavaScript中Boolean.toSource()方法的使用
2015/06/05 Javascript
JavaScript生成验证码并实现验证功能
2016/09/24 Javascript
jquery checkbox的相关操作总结
2016/10/17 Javascript
探究JavaScript中的五种事件处理程序方式
2016/12/07 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
浅谈vue项目打包优化策略
2018/09/29 Javascript
ligerUI的ligerDialog关闭刷新的方法
2019/09/27 Javascript
vue实践---根据不同环境,自动转换请求的url地址操作
2020/09/21 Javascript
ES6的循环与可迭代对象示例详解
2021/01/31 Javascript
[01:43]倾听DOTA2英雄之声 魅惑魔女国服配音鉴赏
2013/06/06 DOTA
Python生成随机密码的方法
2017/06/16 Python
Pycharm 创建 Django admin 用户名和密码的实例
2018/05/30 Python
Python实现的读写json文件功能示例
2018/06/05 Python
python3解析库pyquery的深入讲解
2018/06/26 Python
解决python通过cx_Oracle模块连接Oracle乱码的问题
2018/10/18 Python
浅谈pycharm出现卡顿的解决方法
2018/12/03 Python
python3.7将代码打包成exe程序并添加图标的方法
2019/10/11 Python
Python代码执行时间测量模块timeit用法解析
2020/07/01 Python
python中判断文件结束符的具体方法
2020/08/04 Python
详解python中的lambda与sorted函数
2020/09/04 Python
澳大利亚有机化妆品网上商店:The Well Store
2020/02/20 全球购物
平面设计的岗位职责
2013/11/08 职场文书
西柏坡导游词
2015/02/05 职场文书
2015年幼儿园保育工作总结
2015/05/12 职场文书
MYSQL主从数据库同步备份配置的方法
2021/05/26 MySQL
Python爬虫入门案例之爬取去哪儿旅游景点攻略以及可视化分析
2021/10/16 Python
js判断两个数组相等的5种方法
2022/05/06 Javascript
MySQL批量更新不同表中的数据
2022/05/11 MySQL