DOM性能瓶颈与Javascript性能优化
这两天比较闲,写了两篇关于JS性能缺陷与解决方案的文章(《JS特性性能缺陷及JIT的解决方案》,《Javascript垃圾回收浅析》),主要描述了untyped,GC带来的问题与JIT引擎的解决方案。但相对于Js引擎的问题,我认为DOM导致的性能问题更值得关注。
一.Dom的性能瓶颈及原因
1. 为什么是DOM
标准的xml/html的文本解析协议,常见的有DOM与SAX。在解析速度及内存占用上,SAX比DOM有优势,但为什么浏览器选择DOM解析html?
(1)DOM VS SAX
SAX提供一次性解析文本,不生成对象,Iterator模式访问元素,event-based,PUSH模式触发,简单说:App需要向Parser注册,当Parser遍历xml时,触发调用APP 。想深入体验,用下javax.xml.parsers.SAXParser。这里说个题外话,改进版StAX是PULL模式,但这都不重要了,重要是:一次性文本解析,不生成对象。
DOM解析文本后,生成DOM树。即:一次性文本解析,生成对象。
(2)浏览器选择了DOM
单次效率DOM不如SAX,但SAX不生成对象,浏览器很多操作很难满足,比如:元素定位,元素样式渲染……所以DOM是必然之选。
2. DOM的性能问题
【1】核心问题
当解析的html文件很大时,生成DOM树占用内存较大,同时遍历(不更新)元素耗时也更长。但这都不是重点,DOM的核心问题是:DOM修改导致的页面重绘、重新排版!重新排版是用户阻塞的操作,同时,如果频繁重排,CPU使用率也会猛涨!
DOM操作会导致一系列的重绘(repaint)、重新排版(reflow)操作。为了确保执行结果的准确性,所有的修改操作是按顺序同步执行的。大部分浏览器都不会在JavaScript的执行过程中更新DOM。相应的,这些浏览器将对对 DOM的操作放进一个队列,并在JavaScript脚本执行完毕以后按顺序一次执行完毕。也就是说,在JavaScript执行的过程,直到发生重新排版,用户一直被阻塞。
一般的浏览器中(不含IE),repaint的速度远快于reflow,所以避免reflow更重要。
导致repaint、reflow的操作:
* DOM元素的添加、修改(内容)、删除( Reflow + Repaint)
* 仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)
* 应用新的样式或者修改任何影响元素外观的属性
* Resize浏览器窗口、滚动页面
* 读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE))
【2】其他
某些Javascript框架中,CSS选择器,如:var el = $('.hyddd');由于IE6、7不支持,所以Javascript框架必须通过遍历整个DOM树来寻找对象。
二. 针对DOM问题,Javascript的应对方案
1. 针对repaint、reflow,Nicholas 大叔在他的《Speed up your JavaScript, Part 4》做了详细介绍,这里我也整理一下:
解决问题的关键是:减少因DOM操作,引起的reflow。Nicholas总结了一些方法:
【1】在DOM外,执行尽量多的变更操作。Demo:

// 不好的做法
for (var i=0; i < items.length; i++){
var item = document.createElement("li");
item.appendChild(document.createTextNode("Option " + i);
list.appendChild(item);
}


// 更好的做法
// 使用容器存放临时变更, 最后再一次性更新DOM
var fragment = document.createDocumentFragment();
for (var i=0; i < items.length; i++){
var item = document.createElement("li");
item.appendChild(document.createTextNode("Option " + i);
fragment.appendChild(item);
}
list.appendChild(fragment);

【2】操作DOM前,先把DOM节点删除或隐藏,因为隐藏的节点不会触发重排。Demo如下:

list.style.display = "none";
for (var i=0; i < items.length; i++){
var item = document.createElement("li");
item.appendChild(document.createTextNode("Option " + i);
list.appendChild(item);
}
list.style.display = "";

【3】一次性,修改样式属性。Demo如下:
// 不好的做法
// 这种做法会触发多次重排
element.style.backgroundColor = "blue";
element.style.color = "red";
element.style.fontSize = "12em";

// 更好的做法是,把样式都放在一个class下
.newStyle {
background-color: blue;
color: red;
font-size: 12em;
}
element.className = "newStyle";

【4】使用缓存,缓存临时节点。
// 不好的做法
document.getElementById("myDiv").style.left = document.getElementById("myDiv").offsetLeft +
document.getElementById("myDiv").offsetWidth + "px";
// 更好的做法
var myDiv = document.getElementById("myDiv");
myDiv.style.left = myDiv.offsetLeft + myDiv.offsetWidth + "px";
2. 针选择其的问题,我只能说:没办法…… : (
三. 参考资源
2. 《Speed up your JavaScript, Part 4》
DOM性能瓶颈与Javascript性能优化的更多相关文章
- JavaScript性能优化
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...
- javascript性能优化-repaint和reflow
repaint(重绘) ,repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲 ...
- 摘:JavaScript性能优化小知识总结
原文地址:http://www.codeceo.com/article/javascript-performance-tips.html JavaScript的性能问题不容小觑,这就需要我们开发人员在 ...
- JavaScript性能优化小窍门汇总(含实例)
在众多语言中,JavaScript已经占有重要的一席之地,利用JavaScript我们可以做很多事情 , 应用广泛.在web应用项目中,需要大量JavaScript的代码,将来也会越来越多.但是由于J ...
- JavaScript性能优化小知识总结(转)
JavaScript的性能问题不容小觑,这就需要我们开发人员在编写JavaScript程序时多注意一些细节,本文非常详细的介绍了一下JavaScript性能优化方面的知识点,绝对是干货. 前言 一直在 ...
- 前端性能优化--为什么DOM操作慢? 浅谈DOM的操作以及性能优化问题-重绘重排 为什么要减少DOM操作 为什么要减少操作DOM
前端性能优化--为什么DOM操作慢? 作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩( ...
- JavaScript性能优化篇js优化
JavaScript性能优化篇js优化 随着Ajax越来越普遍,Ajax引用的规模越来越大,Javascript代码的性能越来越显得重要,我想这就是一个很典型的例子,上面那段代码因为会被频繁使用, ...
- Javascript 性能优化的一点技巧
把优秀的编程方式当成一种习惯,融入到日常的编程当中.下图是今天想到的一点Javascript 性能优化的技巧,分享一下,抛砖引玉.
- 高频dom操作和页面性能优化(转载)
作者:gxt19940130 原文:https://feclub.cn/post/content/dom 一.DOM操作影响页面性能的核心问题 通过js操作DOM的代价很高,影响页面性能的主要问题有如 ...
随机推荐
- 掌握 tar 命令让你秒变大牛
导读 相信很多初学者在linux环境下为文件归类整理而犯愁,下面是整理文章的的一些命令与技巧,学习Tar命令将会让你处理文件时更加得心应手. Tar(Tape ARchive,磁带归档的缩写:最初设计 ...
- qlikview 扩展插件制作教程-EchartsGeoMap
效果图 显示效果和echarts官方demo一样,运行速度尚可. 第一次写博客,排版很渣以后慢慢改进. 基础知识 以EchartsGeoMap为例,讲一下怎么制作一个基础的QlikView Ext ...
- oracle 学习笔记(一)
1. 数据库原理 1.1. 数据库简介 1.1.1. 文件存储 对数据的存储需求一直存在.保存数据的方式,经历了手工管理.文件管理等阶段,直至数据库管理阶段. 文件存储方式保存数据的弊端: 缺乏对数据 ...
- js之iframe子页面与父页面通信
iframe子页面与父页面通信根据iframe中src属性是同域链接还是跨域链接,通信方式也不同. 一.同域下父子页面的通信 父页面parent.html <html> <head& ...
- 使用getParts()上传多个文件
<!DOCTYPE html> <html> <head> <title></title> <meta http-equiv=&quo ...
- gl.h报错
以下内容摘自:http://blog.csdn.net/kaphen/article/details/24721999 头文件只有#include <gl\gl.h> //OpenGL H ...
- JavaScript 嵌套 书名号 查询
字符串中查找嵌套书名号 ,一开始想用正则来做的,最后发现正则不可能达到我的需求(可能是我正则理解不够,哈哈),所以写下了这个方法:只做了三层,如果你要更多,可以自己添加,哈哈//提取查询关键字,sou ...
- javase-->基础知识(二)
1.算术运算符 7种:+,-,*,/,%,++,--; --------------------注意不要想当然,按照类型规则来计算 ++在变量前,先加1再取变量使用 --同理 在变量 ...
- MongoDB 安装及其配置
安装: 安装路径d:MongoDB较短便于后续操作 配置: 1.新建data文件夹并在data文件夹下新建db和log文件夹,路径如下 MongoDB\data\db MongoDB\data\log ...
- scp 从远程服务器上一下载文件
scp -P202 xx3.x6.xx.xx:/usr/local/zookeeper-.zip /tmp #指定远程服务器的端口和远程服务器的目标文件 ,最后指定要下载到本的地目录 也可以从远程服务 ...