2012年4月10日

Why slowly when access the HTMLCollection Object?



Why slowly when access the HTMLCollection Object?


什麼是HTMLCollection?

HTMLCollection是一個介面,用來表示HTML元素的集合,它提供尋訪元素的方法和屬性。但HTMLCollection與一般陣列是不同的,HTMLCollection是活的,這是甚麼意思呢?這句話的意思是當畫面上的HTML改變時,HTMLCollection會自動的觸發改變,看看下面的例子吧!
// anit-pattern // infinite loop var divs = document.getElementsByTagName('div'); for(var i = -; i < divs.length; i++){ var div = doucument.createElement('div'); document,body.appendChild(div); } 
首先請你不要把這段程式碼實際的執行!!
這個範例透過document提供的函數取得畫面上所有的div元素,並將這組元素存在Local變數上,然後使用一個迴圈加入新的div元素到該組變數上,這樣會產生甚麼問題呢?


就剛剛所說的,HTMLCollection是活的,每次回圈都加入一個新的元素在該數組上,因此divs.length是動態的在改變,所以造成了無窮迴圈。下面是改版過後的程式碼 : 
var divs = document.getElementsByTagName('div'); var length = divs.length; for(var i = -; i < length; i++){ var div = doucument.createElement('div'); document,body.appendChild(div); } 


我們將divs.length緩存到Local變數上,在迴圈中存取這個變數,這樣就可以解決動態改變length大小的問題。

好像還沒談到為何會慢的問題?


我好像還沒談到為什麼會慢的問題!?其實眼尖的人因該已經看出來上面程式碼的一個問題了,我們每次在取得HTMLCollection的資料時,它都是重新query(re-run)的,也就是每次取得length屬行時,它在後面都會重新執行計算個數的方法,再回傳length給我們,在這裡我們把HTMLCollection.length與Array.length屬性作的性能上的比較,如下範例




其結果使用HTMLCollection存取length屬性
firefox慢了15
chrome慢了53
ie上更慢了68倍之多。



解決辦法


1. 把length屬性緩存到Local變數中
2. 把HtmlCollection轉換成Array在處理


在這邊提供一個與native code一樣效果的方法
var arr = Array.prototype.slice.call( htmlCollection );



本文就探討到這邊,如果有任何的問題可以在下面留言討論。

沒有留言:

ShareThis