2017-06-02 78 views
0

當我遍歷由querySelectorAll獲得的節點列表併爲每個節點添加一個新類時,它比getElementsByClassName(100ms)獲得的時間(3ms)少得多。爲什麼?querySelectorAll vs getElementsByClassName

var container = document.getElementById('box-container'); 
var button = document.getElementById('button'); 

for (var i = 0; i < 3000; i++) { 
    var div = document.createElement('div'); 
    div.classList.add('box'); 
    div.index = i; 
    container.appendChild(div); 
} 

button.addEventListener('click', function() { 

    var box1 = container.getElementsByClassName('box'); 
    for (var i = 1;i < box1.length; i+=2){ 
     box1[i].classList.toggle('gray'); 
    }; 

    var box2 = container.querySelectorAll('.box'); 
    for (var i = 1;i < box2.length; i+=2){ 
     box2[i-1].classList.toggle('gray'); 
    }; 

}); 

回答

0

區別在於您正在運行的列表的類型。
box1是當DOM改變時更新的NodeList(a.k.a活節點列表)。 box2是一個數組,它是一個non-live列表 - 所以更改DOM不會影響它。 當您在box1上迭代時發生的情況是,在每個類切換上,更新box1列表,這會導致開銷。 這是一個測試,你可以輕鬆地運行:

var container = document.getElementById('box-container'); 
var button = document.getElementById('button'); 

for (var i = 0; i < 6000; i++) { // added 3000 more to challenge modern browsers... 
    var div = document.createElement('div'); 
    div.classList.add('box'); 
    div.index = i; 
    container.appendChild(div); 
} 

button.addEventListener('click', function() { 

    var box1 = container.getElementsByClassName('box'); 
    for (var i = 1; i < box1.length; i += 2) { 
     box1[i].classList.toggle('gray'); 
    } 

    var deadBox1 = []; 
    for (i = 0; i < box1.length; i++) { 
     deadBox1[i] = box1[i]; 
    } 

    for (var i = 1; i < deadBox1.length; i += 2) { 
     deadBox1[i].classList.toggle('gray'); 
    } 

    var box2 = container.querySelectorAll('.box'); 
    for (i = 1; i < box2.length; i += 2) { 
     box2[i - 1].classList.toggle('gray'); 
    } 

}); 

現在運行的鍍鉻性能(或時間表)工具。您可以在這裏看到差異: See the diff between the <code>box1</code> and the <code>deadBox1</code> toggle loops performance