Коллекция объектов DOM в Javascript – почему я не могу выполнить обратный ход с помощью Array.reverse()?
-
09-06-2019 - |
Вопрос
В чем может быть проблема с обращением массива объектов DOM, как в следующем коде:
var imagesArr = new Array();
imagesArr = document.getElementById("myDivHolderId").getElementsByTagName("img");
imagesArr.reverse();
В Firefox 3, когда я вызываю reverse()
метод, сценарий прекращает выполнение и отображает следующую ошибку в консоли панели инструментов веб-разработчика:
imagesArr.reverse is not a function
А imagesArr
переменную можно перебирать с помощью цикла for и таких элементов, как imagesArr[i]
доступен, так почему же он не рассматривается как массив при вызове reverse()
метод?
Решение
Потому что имя getElementsByTag фактически возвращает структуру NodeList.Он имеет аналогичный массив, как и свойства индексирования, для удобства синтаксиса, но это нет массив.Например, набор записей фактически постоянно динамически обновляется — если вы добавите новый тег img под myDivHolderId, он автоматически появится в imagesArr.
Видеть http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-536297177 для большего.
Другие советы
getElementsByTag()
возвращает NodeList вместо массива.Вы можете преобразовать NodeList в Array, но учтите, что массив будет другим объектом, поэтому его изменение не повлияет на положение узлов DOM.
var listNodes = document.getElementById("myDivHolderId").getElementsByTagName("img");
var arrayNodes = Array.slice.call(listNodes, 0);
arrayNodes.reverse();
Чтобы изменить положение, вам придется удалить узлы DOM и снова добавить их в нужное положение.
Array.prototype.slice.call(arrayLike, 0)
— отличный способ преобразовать массив в массив, но если вы используете библиотеку JavaScript, это может оказаться еще лучшим/более быстрым способом сделать это.Например, jQuery имеет $.makeArray(arrayLike)
.
Вы также можете использовать методы Array непосредственно в NodeList:
Array.prototype.reverse.call(listNodes);
getElementsByTag()
возвращает NodeList вместо массива.Вам нужно преобразовать NodeList в массив, а затем перевернуть его.
var imagesArr = [].slice.call(document.getElementById("myDivHolderId").getElementsByTagName("img"), 0).reverse();
Я знаю, что этот вопрос старый, но я думаю, что он нуждается в небольшом разъяснении, поскольку некоторые ответы здесь устарели, поскольку W3C изменил определение и, следовательно, возвращаемое значение этих методов. getElementsByTagName()
и getElementsByClassName()
Эти методы на момент написания этого ответа вернуть объект - пустой или нет - типа HTMLCollection
и нет NodeList
.
Это как разница между свойствами children
который возвращает объект типа HTMLCollection
поскольку он состоит только из элементов и исключает узлы текста или комментариев, и childNodes
который возвращает объект типа NodeList
поскольку он может содержать и другие типы узлов, такие как текст и комментарии.
Примечание:Я бы пошел по касательной и выразил свое непонимание того, почему querySelectorAll()
метод в настоящее время возвращает NodeList
и не HTMLCollection
поскольку он работает исключительно с узлами элементов в документе и больше ни с чем.
Вероятно, это как-то связано с потенциальным охватом других типов узлов в будущем, и они выбрали более перспективное решение, кто знает на самом деле?:)
РЕДАКТИРОВАТЬ:Думаю, я понял причину этого решения выбрать NodeList
и не HTMLCollection
для querySelectorAll()
.
Поскольку они построили HTMLCollection
быть исключительно и полностью живым, и поскольку этот метод не нуждается в этой живой функциональности, они решили NodeList
вместо этого, чтобы наилучшим образом служить своей цели экономично и эффективно.
Ваша первая строка не имеет значения, поскольку она не приводит к присвоению переменной, javascript работает наоборот.imagesArr не имеет типа Array(), а имеет тип возвращаемого значения getElementsByTagName("img").В данном случае это HtmlCollection в Firefox 3.
Единственными методами этого объекта являются индексаторы и длина.Чтобы работать в обратном порядке, просто выполните итерацию в обратном направлении.