querySelectorAll 与 getElementsByClassName

1 performance loops selectors-api getelementsbyclassname

当我循环通过 querySelectorAll 获得的节点列表并为每个节点添加一个新类时,它花费的时间(3ms)比 getElementsByClassName(100ms) 获得的时间少得多。为什么?

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');
  };

});
Run Code Online (Sandbox Code Playgroud)

ycc*_*eam 5

区别在于您所运行的列表类型。
box1是一个 NodeList(又名活动节点列表),当 DOM 更改时会更新。 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');
    }

});
Run Code Online (Sandbox Code Playgroud)

现在运行 chrome 性能(或时间线)工具。您可以在这里看到差异: 查看 <code>box1</code> 和 <code>deadBox1</code> 切换循环性能之间的差异

  • box1 使用 getElementsByClassName 返回实时 HTMLCollection。document.querySelectorAll() 方法返回一个静态 NodeList。 (3认同)