给页面渲染时间加速 干掉Dom Level 0 Event


Posted in Javascript onDecember 19, 2012

现在的web应用越来越复杂,需要响应各种各样的用户触发事件,因而也就不可避免的,需要给我们的html页面上的dom元素增加事件监听函数.

我们知道给dom元素绑定事件监听函数的方法有如下3种:
1 : 页面html:

<button onclick=”test();”></button>

2: 页面html:
<button id=”btn”></button>

Javascript:
document.getElementById(“btn”).onclick = test;

3: 页面html:
<button id=”btn”></button>

Javascript:
document.getElementById(“btn”).atachEvent(“onclick”,test); //ie

这3种方法的功能效果和差异,大家都了解,在此就不在赘述了,但是这3种方法,对页面渲染的速度,资源的消耗,却是有很大不同的.

正文后面的html代码是一个demo页面,大家可以用ie浏览器打开,通过注释不同的代码段,查看页面运行效果.
可以看到第一种方式的效率是最低的,随着页面节点的增多,页面渲染时间急剧增加,在ie7下运行,大概670ms;
第二种方式明显好一些,在ie7下,大概250ms
而第三种方式则是最快的方法,也是web前端开发推荐的标准写法,在ie7下,大概188ms;
然后我们去掉事件绑定的逻辑,发现只渲染dom元素,不绑定事件的时间,仅仅125ms,可见事件绑定的时间消耗还是很大的 ,尤其是第一种方式,也就是Dom Level 0 Event,最为耗时.

另外,大家运行各段代码的时候,不妨打开任务管理器,找到浏览器对应的进程,查看代码运行时cpu的消耗以及内存的使用.
我们可以看到,Dom Level 0 Event,对cpu的消耗明显要高很多.

对内存的消耗分析:
重新打开浏览器,空白页面的内存占用量大概是37M,虚拟内存为28M,页面渲染后:
1 内存使用 54M,虚拟内存41M
2 内存使用44M,虚拟内存31M
3 内存使用44M,虚拟内存31M
可见Dom Level 0 Event对内存的消耗,也远远超出了其它方式.
为什么Dom Level 0 Event会这么消耗系统资源呢?对cpu和内存的消耗都远远超出了其它方式.我们来做一个简单分析.

为了便于分析,我们不妨修改一下我们的代码 <button onclick=”debugger;test();”></button> ,然后运行页面,在ie的script debugger里我们找到堆栈调用这一项,可以看到有一个anonymos function,这个function是从何而来的呢.原来浏览器在对Dom Level 0 Event做绑定的时候,会自动生成一个包含我们的代码的匿名函数,然后把这个匿名函数绑定到事件.类似于如下方式:

document.getElementById(“btn”).onclick = function(event){ 
test(); 
} ;

而ie浏览器又没有足够的智能,区分出众多内部功能完全一致的匿名函数并合并它们的引用,所以导致了随着dom事件绑定的越来越多,匿名函数的个数也越来越多.因为要声明数量众多的事件处理匿名函数,也就不难明白,为什么会消耗如此多的系统资源了.

随着dom元素的增多,这个资源消耗就会越来越严重.而且我们可以尝试着刷新一下页面,发现随着刷新的次数增加,页面运行越来越慢,cpu消耗也越来越多,内存也会有少量增加.可见,Dom Level 0 Event 还会带来少量的内存泄露.至于时间的延长,cpu消耗的加聚,推测是因为浏览器忙于释放众多的匿名函数所占用的资源所带来的后果.

进一步深入,由于ie浏览器是基于冒泡的事件模型,子元素的event会冒泡到父元素,所以更极致的优化,是去掉众多子元素的事件绑定,而将事件绑定到父元素,在正文后的demo中,也有这方面的尝试,可以看到不仅cpu,内存消耗最低,时间上也跟渲染干净的html页面是一样的.

所以我们在页面事件绑定中,要尽量避免Dom Level 0 Event,而且要尽可能的将事件上升.(当然也要考虑事件处理的灵活性).
demo:

<BODY> 
<ul id="list"></ul> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
var $ = function(id){ 
return document.getElementById(id) 
}; 
function test(){ 
alert(1) 
} 
var ul = $("list"); 
var count = 5000; 
// ie7 
//--> 
</SCRIPT> 
<script> 
var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li onclick="test();">'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
alert(new Date - d); 
//670 刷新时时间增加 85 
</script> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
alert(new Date - d); */ 
//125 
//--> 
</SCRIPT> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
var li = document.getElementsByTagName("li"); 
var l = li.length; 
for(var i=0;i<l;i++){ 
li[i].onclick = test; 
} 
li = null; 
alert(new Date - d);*/ 
//250 
//--> 
</SCRIPT> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
var li = document.getElementsByTagName("li"); 
var l = li.length; 
for(var i=0;i<l;i++){ 
li[i].attachEvent("onclick",test); 
} 
li = null; 
alert(new Date - d);*/ 
//188 
//--> 
</SCRIPT> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
ul.attachEvent("onclick",test); 
alert(new Date - d);*/ 
//125 
//--> 
</SCRIPT> 
</BODY>
Javascript 相关文章推荐
jQuery学习笔记之 Ajax操作篇(二) - 数据传递
Jun 23 Javascript
Ajax局部更新导致JS事件重复触发问题的解决方法
Oct 14 Javascript
jQuery中:gt选择器用法实例
Dec 29 Javascript
JavaScript实现的SHA-1加密算法完整实例
Feb 02 Javascript
jQuery实现背景滑动菜单
Dec 02 Javascript
js/jq仿window文件夹移动/剪切/复制等操作代码
Mar 08 Javascript
前端MVVM框架解析之双向绑定
Jan 24 Javascript
浅谈Angular单元测试总结
Mar 22 Javascript
微信小程序动态显示项目倒计时
Jun 20 Javascript
AutoJs实现刷宝短视频的思路详解
May 22 Javascript
vue 路由meta 设置导航隐藏与显示功能的示例代码
Sep 04 Javascript
vue通过接口直接下载java生成好的Excel表格案例
Oct 26 Javascript
img onload事件绑定各浏览器均可执行
Dec 19 #Javascript
JavaScript实现快速排序(自已编写)
Dec 19 #Javascript
js 使用form表单select类实现级联菜单效果
Dec 19 #Javascript
JS限制上传图片大小不使用控件在本地实现
Dec 19 #Javascript
JS上传图片前的限制包括(jpg jpg gif及大小高宽)等
Dec 19 #Javascript
js限制文本框输入长度两种限制方式(长度、字节数)
Dec 19 #Javascript
ajax java 实现自动完成功能
Dec 19 #Javascript
You might like
PHP操作MongoDB GridFS 存储文件的详解
2013/06/20 PHP
修改ThinkPHP缓存为Memcache的方法
2014/06/25 PHP
在Ubuntu 14.04上部署 PHP 环境及 WordPress
2014/09/02 PHP
jquery插件之信息弹出框showInfoDialog(成功/错误/警告/通知/背景遮罩)
2013/01/09 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
Javascript基础教程之数据类型 (布尔型 Boolean)
2015/01/18 Javascript
跟我学习JScript的Bug与内存管理
2015/11/18 Javascript
微信小程序之仿微信漂流瓶实例
2016/12/09 Javascript
windows下vue.js开发环境搭建教程
2017/03/20 Javascript
JavaScript验证知识整理
2017/03/24 Javascript
Vuex之理解state的用法实例
2017/04/19 Javascript
基于jQuery解决ios10以上版本缩放问题
2017/11/03 jQuery
解决vue项目报错webpackJsonp is not defined问题
2018/03/14 Javascript
vue组件中iview的modal组件爬坑问题之modal的显示与否应该是使用v-show
2019/04/12 Javascript
JavaScript闭包相关知识解析
2019/10/19 Javascript
JavaScript动画实例之粒子文本的实现方法详解
2020/07/28 Javascript
React倒计时功能实现代码——解耦通用
2020/09/18 Javascript
[01:03:37]Secret vs VGJ.S Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
Python命名空间详解
2014/08/18 Python
Python处理文本文件中控制字符的方法
2017/02/07 Python
Pycharm学习教程(5) Python快捷键相关设置
2017/05/03 Python
解决python3中解压zip文件是文件名乱码的问题
2018/03/22 Python
在python中实现将一张图片剪切成四份的方法
2018/12/05 Python
详解python运行三种方式
2019/05/13 Python
python从list列表中选出一个数和其对应的坐标方法
2019/07/20 Python
python识别验证码图片实例详解
2020/02/17 Python
AVIS安飞士奥地利租车官网:提供奥地利、欧洲和全世界汽车租赁
2016/11/29 全球购物
俄罗斯皮肤健康中心:Pharmacosmetica.ru
2020/02/22 全球购物
戴森香港官方网站:Dyson香港
2021/02/11 全球购物
Lentiamo丹麦:购买便宜的隐形眼镜
2021/01/13 全球购物
美德好少年事迹材料
2014/01/19 职场文书
省三好学生申请材料
2014/01/22 职场文书
小学数学教研活动总结
2014/07/01 职场文书
会计专业自荐书
2014/07/08 职场文书
公司奖励通知
2015/04/21 职场文书
CSS3 天气图标动画效果
2021/04/06 HTML / CSS