Разница между getElementsByClassName и querySelectorAll?

С моей точки зрения,

var elems = document.querySelectorAll(".class");
var elems = document.getElementsByClassName("class");

должен возвращать те же самые вещи. Однако, когда я пытаюсь удалить класс из всех элементов с помощью

for (var i = 0; i < elems.length; ++i)
  elems[i].className = "";

Я получаю разные результаты. querySelectorAll успешно удаляет классы из всех элементов, но getElementsByClassName удаляет только классы из примерно половины элементов.

Что происходит?

Ответ 1

querySelectorAll не возвращает живые элементы DOM. Последующие изменения в структуре базового документа не будут отражаться в объекте NodeList, возвращаемом querySelectorAll. Это означает, что вместо этого объект будет содержать список соответствующих узлов элемента, которые были в документе во время создания списка.

getElementsByClassName возвращает живые элементы DOM. Любое последующее изменение, внесенное в эти элементы DOM, будет отражено в списке.

Ответ 2

Чтобы расширить ответ Anirudha, при изменении имен классов в реальном списке элементов, полученных с помощью getElementsByClassName, вы уменьшаете количество результатов (так как элементы, доступные в списке, только там, потому что они имеют имя класса).

Таким образом, ваше свойство elems.length уменьшается на единицу с каждой итерацией, и вы делаете это только через половину элементов.