getElementsByClassName не возвращает фиксированный ответ

В Javascript я получаю элементы данного класса, используя:

A = document.getElementsByClassName("someclass");
> A contains elements e1, e2, e3, e4

Затем я изменяю класс одного из этих элементов:

document.getElementById("e2").className = "anotherclass";

К моему большому удивлению, массив A был автоматически изменен в процессе !!

> A contains elements e1, e3, e4

Я думал, что массив, возвращаемый getElementsByClassName, останется тем же, что и был назначен.

  • Как это возможно? Это намеренное поведение?
  • Есть ли простой способ изменить это?

Вот JSfiddle.

Обратите внимание, что это также верно для getElementById.


person fffred    schedule 02.05.2014    source источник
comment
К вашему сведению, если вы не хотите, чтобы возвращенный nodeList был живым (как объяснялось в ответах), вы можете переключиться на использование document.querySelectorAll(), который возвращает статический nodeList и имеет лучшую поддержку браузера, чем document.getElementsByClassName().   -  person jfriend00    schedule 03.05.2014
comment
@ jfriend00 - Но разве изменение класса не будет обновляться в неактивном списке узлов. Я ответил на то же самое, но затем проверил его jsfiddle.net/USmsH/2< /b>, и кажется, что неактивный список узлов статичен только в отношении фактических изменений DOM, таких как добавление/удаление дочерних элементов и т. д.   -  person adeneo    schedule 03.05.2014
comment
@adeneo: в вашей демонстрации показаны все четыре элемента в списке (тестирование в Firefox).   -  person cookie monster    schedule 03.05.2014
comment
@adeneo - Неживой список узлов - это не что иное, как статический список узлов. Это не изменится. Посмотрите консоль здесь: jsfiddle.net/jfriend00/nDkga   -  person jfriend00    schedule 03.05.2014
comment
Конечно, он показывает все четыре элемента в консоли, но если вы посмотрите на вопрос, OP меняет класс, и он обновляется в живом списке узлов, но это происходит и в неживом списке узлов. Консоль показывает все четыре элемента, а класс второго изменен. Если вы добавите или удалите элементы, это будет фактическим изменением структуры DOM, которое не отражается в неактивном списке узлов, отсюда и мой комментарий выше.   -  person adeneo    schedule 03.05.2014


Ответы (2)


Это потому, что A не является Array. getElementByClassName возвращает HTMLCollection, который постоянно обновляется в связи с изменениями в документе.

Самый простой способ преобразовать объект, подобный массиву, в массив, это сделать так:

var A = ...

// With ES5 code
var A_array = Array.prototype.slice.call(A);

// With ES6 code
var A_array = Array.from(A);

Или вы можете получить NodeList вместо этого через querySelectorAll, который не будет обновляться в реальном времени.

var A = document.querySelectorAll('.someclass');
person loganfsmyth    schedule 02.05.2014
comment
На самом деле, я думаю, что проще всего было бы использовать вместо этого document.querySelectorAll(). - person jfriend00; 03.05.2014
comment
@ jfriend00 Ха, да, хорошая мысль. - person loganfsmyth; 03.05.2014

Эти функции возвращают активные списки узлов. Это означает, что они автоматически обновляются, чтобы отражать текущее содержимое DOM.

См. NodeList документацию.

person Barmar    schedule 02.05.2014
comment
Не все nodeList активны. document.querySelectorAll() возвращает неживое nodeList. Вы должны проконсультироваться с конкретной функцией, чтобы узнать, возвращает ли она живое или неживое nodeList. - person jfriend00; 03.05.2014
comment
Я знаю это. Об этом говорится в документации, на которую я ссылался. - person Barmar; 03.05.2014
comment
Я хотел сказать, что вы должны обратиться к документу для функции, которую вы используете, а не к документу nodeList, чтобы узнать, активен ли ваш nodeList или нет. В этом случае, на мой взгляд, документ для getElementsByClassName() был бы более актуальным. - person jfriend00; 03.05.2014
comment
Хм, в документации MDN для getElementsByClassName не упоминается, что это живой NodeList. w3fools тоже не упоминает об этом, но я бы не стал ссылаться на них, даже если бы они это сделали. Есть лучшая ссылка, которую я могу добавить к своему ответу? - person Barmar; 03.05.2014
comment
Это промах, что документ MDN не объясняет этого. У меня нет лучшего справочника в стиле MDN. - person jfriend00; 03.05.2014