為js做效能測試

iteye_3829發表於2013-05-18

1. 批量增加Dom 
儘量使用修改innerHTML的方式而不是用appendChild的方式; 因為使用innerHTML開銷更小,速度更快,同時也更加記憶體安全. 
有一點需要注意的是,用innerHTML方式新增時,一定不要在迴圈中使用 innerHTML += 的方式新增,這樣反而會使速度減慢; 而是應該中間用array快取起來,迴圈結束後呼叫 xx.innerHTML = array.join(‘’);的方式,或者至少儲存到string中再插到innerHTML中. 
針對使用者列表一塊採用這種方式優化後,載入速度提升一倍. 
2. 單個增加Dom 
這裡是指要將新節點載入到一個內容不斷變化的節點的情形,對於內容穩定的節點來說,隨便怎麼加都沒有問題. 但是對於有動態內容的節點來說,為其新增子節點儘量使用 dom append的方式. 
這是因為,dom append不會影響到其他的節點;而如果修改innerHTML屬性的話,該父節點的所有子節點都會從dom樹中剝離,再根據新的innerHTML值來重繪子節點dom樹;所有註冊到原來子節點的事件也會失效. 
綜上,如果在一個有動態內容的節點上 出現了 innerHTML += 的程式碼,就該考慮是否有問題了. 
3. 建立Dom節點 
用createElement方式建立一個dom節點,有一個很重要的細節: 在執行完createElement程式碼之後,應該馬上append到dom樹中; 否則,如果在將這個孤立節點載入到dom樹之前所做的賦值它的屬性和innerHTML的操作都會引發該dom片段記憶體無法回收的問題. 這個不起眼細節,一旦遇到大量dom增刪操作,就會引發記憶體的災難. 
4. 刪除Dom節點 
刪除dom節點之前,一定要刪除註冊在該節點上的事件,不管是用observe方式還是用attachEvent方式註冊的事件,否則將會產生無法回收的記憶體. 
另,在removeChild和innerHTML=’’二者之間,儘量選擇後者. 因為在sIEve(記憶體洩露監測工具)中監測的結果是用removeChild無法有效地釋放dom節點. 
5. 建立事件監聽 
現有的js庫都採用observe方式來建立事件監聽,其實現上隔離了dom物件和事件處理函式之間的迴圈引用,所以應該儘量採用這種方式來建立事件監聽. 
6. 監聽動態元素 
Dom事件預設是向上冒泡的,發生在子節點中的事件,可以由父節點來處理. Event的 target/srcElement 仍是產生事件的最深層子節點. 這樣,對於內容動態增加並且子節點都需要相同的事件處理函式的情況,可以把事件註冊上提到父節點上,這樣就不需要為每個子節點註冊事件監聽了. 
同時,這樣做也避免了產生無法回收的記憶體.即使是用Prototype的observe方式註冊事件並在刪除節點前呼叫stopObserving,也會產生出少量無法回收的記憶體,所以應該儘量少的為dom節點註冊事件監聽. 
所以,當程式碼中出現在迴圈裡註冊事件時,也是我們該考慮事件上提機制的時候了. 
7. HTML提純 
HTML提純體現的是一種各負其責的思想. HTML只用來顯示,儘量不出現和顯示無關的屬性.比如onclick事件,比如自定義的物件屬性. 
事件可以用前面的方法避免, 物件屬性指的是這樣的一種情景: 通常情況下,動態增加的內容都是有個物件和它對應,比如聊天室的使用者列表,每個顯示使用者的dom節點都有一個user物件和它對應,這樣在html中,應該僅保留一個id屬性和user物件對應,而其他的資訊,則應通過user物件去獲取. 


    基於PrototypeJS,寫了一個Dom生成器,以提供簡單高效的HTML操作介面的語法和語義優化: 

作者:長沙
1. 使用類似JSONML的格式(HTML in JSON)描述DOM結構,以補充HTML轉義字串的表達形式,規範格式中可支援以下HTML語義: 
l 標籤名 
l 屬性(識別符號,類名,事件名,內聯樣式等) 
注:事件名上註冊的偵聽函式將自動通過Event.observe方式新增 
l 巢狀標籤 
格式規範可簡單描述為: 

tag:string, // 元素的標記名,如果沒有,預設為div 
children|cn: string|Array|json, // 子結點對應的json陣列或位元組點的html或單個json 
html:string, // 對應的html,如果有cn或children屬性就忽略 
style:function|string|json, // 元素的樣式,可以是函式,字串,json物件 
cls:string, // 元素的class屬性的值 
x:y // x表示其他名字,y表示變數值、非空字串 
onXXX: function // 以on為首的屬性是事件偵聽器 

一個具體的例子為: 
var list = DomBuilder.append('my-div', { 
tag : 'ul', 
cls : 'my-list', 
children : [ 

tag : 'li', 
id : 'item1', 
html : 'List Item 1', 
onclick : function() { 
alert('List Item1 Clicked') 

}, 

tag : 'li', 
id : 'item2', 
html : 'List Item 2', 
customattr : 'customValue' 
}] 
}); 
2. 在實際修改DOM結構時,提供兩種方式可供呼叫者選擇,以便應需使用: 
l W3C標準DOM操作(appendChild, removeChild)方式 
l 使用innerHTML,insertAdjacentHTML等的實效模式 
一個具體例子為: 
DomBuilder.useDom = true; //顯示申明使用W3C Dom操作方式 
3. 另外提供DOM節點的有效回收方法 
var abandoned = DomBuilder.destroy(list); //將DOM節點從文件中移除

 

csdn

相關文章