不少人都知道:由于操做DOM代价大、耗性能,因此要尽可能减小DOM操做,可是,为何代价大?耗性能呢?目前的硬件水平比当年高出好几倍了还须要这么作吗?javascript
下面,就我看过的资料整理以下:css
1、DOM其实就是一个javascript对象,每一个DOM节点就是这个对象里面的属性。因此,操做DOM其实就是修改js对象的属性值(就比如:js.a = "b"),这个js对象改变后,会触发一些浏览器的行为,这个行为(好比layout和paint)就是代价大、耗性能的罪魁祸首了。html
首先,从浏览器层面入手,有渲染引擎和js引擎(具体请看各浏览器内核汇总)。java
渲染引擎工做:web
上图为Gecko内核(Opera浏览器12.17之前的版本)的渲染流程chrome
上图为Webkit内核(Chrome 28之前版本和Safari)的渲染流程数组
layout(布局)和paint(绘制)是代价最大的,layout就是布局变更形成从新计算(耗CPU,有时也很耗内存),paint就是调用浏览器UI引擎进行渲染展现页面(耗CPU和内存)。paint设计到另外一个引擎的细节,暂不讨论(先当成是java中用awt绘制panel同样耗性能耗资源吧)。下面详细说下layout如何耗性能耗资源:浏览器
layout(布局),主要是计算文档中元素的位置、大小等信息,是渲染工做的第三步。缓存
在HTML被加载时会进行layout,样式改变会致使layout,js执行的时候涉及到布局信息都会致使layout,估计这时候快疯了,那么多样式,每一个样式、每一个js都layout一次,岂不是一个页面要layout几百万次。。。哈哈,别担忧,浏览器仍是精明的,对于layout行为是lazy的,不会傻到每一个样式进行一次layout,对于CSS和JS都会把须要layout行为的数据缓存到一个队列中,当上下文完成执行后进行一次layout(css好比:结点的样式描述完。js好比:一个代码块执行完)。jsp
浏览器的lazy会带来另一个问题,layout信息在队列中的时候,我须要获取DOM节点信息就获取不到了,这时候浏览器就会提早执行一次layout,这就是DOM操做耗性能耗资源的罪魁祸首。
致使提早layout的常见状况(经过chrome浏览器自带的控制台能够看到):
一、经过js获取DOM属性
二、增/删/DOM节点
三、改变浏览器窗口大小
四、改变字体
五、激活css伪类
六、修改DOM的属性,涉及到大小、位置等(该颜色不会激活提早的layout)
七、其余js操做。。。
还有,特别重要的。。。动画的每一帧都会致使layout,为了减小动画带来的layout性能损失,能够动画元素绝对定位,使其脱离文本流。另外,requestAnimationsFrame也能够把layout积累后进行。另外,HTMLCollection对象最好缓存,不然layout次数将乘以数组的长度系数,还有就是减小DOM元素的嵌套深度,并优化CSS的深度。
根据性能测试(呵呵,别人测的,我没测过)显示,假设DOM元素为5千(业内好像都以这个为临界点),减小DOM操做,能够大大减小客户端的性能消耗,假如是手机端更为明显,如DOM操做太频繁,手机端会因内存爆满或CPU占用过分而出现浏览器闪退现象。
这还只是layout形成的性能问题。。。paint形成的性能问题一样严重。。。然而。。。时代在进步,硬件水平日新月异,其实,只要内存有4G,CPU是双核1.8G以上,用最新的浏览器,就不用考虑这些问题啦,233~~~
参考资料:
http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
测试方式:
https://jsperf.com/getelementsbyclassname-vs-queryselectorall/162
http://jsperf.com/getelementbyid-vs-queryselector/218