dom操做中的js優化

頻繁地對於DOM進行操做的非常損耗性能,但在富網頁應用中咱們編寫腳本無可避免地要跟DOM打交道,到底怎麼才能優化這個性能瓶頸呢,大體從如下三種狀況去考慮: html

訪問和修改DOM元素chrome

 

修改DOM樣式,會形成頁面的重繪和從新排版數組

 

經過DOM事件處理程序來響應用戶瀏覽器

 

訪問和修改DOM元素app

  在瀏覽器中,DOM的實現和Javascript的實現一般是保持相互獨立的。下面瞭解一下主流瀏覽器的渲染引擎和JS引擎:ide

  瀏覽器     渲染引擎(內核)     JS引擎  
IE   mshtml.dll(Trident)   JScript
Chrome   WebCore(WebKit)   V8
FireFox   Gecko    Spider-Monkey/TraceMonkey 
Safari   WebCore(WebKit)    JavaScriptCore/SquirrelFish 
 

訪問DOM元素的代價就是交一次「橋費」,修改DOM元素則會致使瀏覽器從新計算頁面的幾何變化。若是是循環修改DOM元素,其代價可想而知。以下代碼:函數

 
function innerHTMLLoop1(){
    for(var count=0;count<10000;count++){
      document.getElementById("test").innerHTML +="增長內容";
    }
}

  在這段代碼中,每循環一次都要對DOM元素訪問兩次:一次是讀取innerHTML屬性的內容,另外一次是把新的內容寫入它。因此一個優化的辦法就是使用一個局部變量存儲更新後的內容,在循環結束時再一次性寫入:oop

function innerHTMLLoop2(){
  var content ="";
   for(var count=0;count<10000;count++){
      content +="增長內容";
    }
   document.getElementById("test").innerHTML += content ;
}
很明顯,innerHTMLLoop2交的「橋費」明顯要少,由於它只訪問了兩次DOM元素,一次讀入,一次寫入。

 

更新頁面的兩種方法性能比較:innerHTML和DOM方法(如document.creatElment)。性能差異不大,innerHTML好一些,使用簡單嘛。另外還有一個更新頁面的方法是節點克隆--element.cloneNode()。性能

 

HTML集合的操做優化

HTML集合是用於存放DOM節點引用的類數組對象。可經過下列的方法或屬性獲得這樣的集合:

document.getElementsByName()
document.getElementsByTagName()
document.getElementsByClassName()
document.images 返回對文檔中全部 Image 對象引用
document.links  返回對文檔中全部 Area 和 Link 對象引用
document.forms 返回對文檔中全部 Form 對象引用
document.forms[0].elements 返回對文檔中第一個表單的全部元素
 

HTML集合會實時查詢文檔信息,也就是說當你要用到這個集合時,它會自動查詢文檔的最新信息。請看以下代碼:

 

var allDivs = document.getElementsByTagName("div");   
for(var i=0;i<allDivs.length;i++){
       document.body.appendChild(document.createElement("div"));   
}

例如像上面的那段代碼實際上是個死循環,由於每一次訪問div集合的length屬性,它都會從新計算文檔中的div元素數目。這就是html集合低效率的來源。要改進代碼就用一個局部變量保存div集合的length屬性:
 

for(var i=0, len=allDivs.length; i<len; i++){...}


訪問HTML集合的length比數組的length要慢,因此要訪問這種集合類的數目length,咱們都應該先用一個局部變量去保存它:
 

var len = 集合.length;

 
另外,訪問數組的元素要比訪問HTML集合的元素要快。因此咱們能夠先把HTML集合轉換成數組纔去進行相應的操做:
 
//HTML集合轉換成數組  
function toArray(coll){
    for(var a=[], i=0, len=coll.legnth; i<len; i++){
      a[i] = coll[i];
    }
    return a;
  }  
//使用  
var coll = document.getElementsByTagName("div");  
var divs = toArray(coll);
 
有人可能會問,這樣多用了一個數組副本到底值不值得?這個卻是要看狀況吧。不過另一種選擇,使用局部變量:
function loopColletion(){
    var coll = document.getElmentsByTagName("div");
    var len = coll.length;
    var el = null;
    for(var i = 0; i<len; i++){
      el = coll[i];
      //而後訪問局部變量el
    }
  }
 
許多瀏覽器提供了API函數返回元素節點,這些API都是原生的,因此可用的話就儘可能用。下圖列舉了一些DOM的屬性:

 

上圖列舉的全部屬性能被FF,safari,chrome,opera所支持,ie6-8只支持children。

  遍歷children比childNodes更快,由於集合項少了。HTML源碼中的空格其實是文本節點,但他們不包含在children中。

另外還有兩個比較好的選擇器API:document.querySelectorAll()和document.querySelector()。前者接收一個CSS選擇器字符串參數並返回一個NodeList類數組對象而不是返回HTML集合,後者只返回符合查詢條件的第一個節點。很遺憾IE六、7不支持這兩個API。

相關文章
相關標籤/搜索