不少人都知道:由於操做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