Наиболее эффективный способ преобразовать HTMLCollection в массив
Как более эффективно преобразовать HTMLCollection в массив, нежели итерировать по содержимому коллекции и вручную добавлять каждый элемент в массив?
5 ответ(ов)
Не уверены, что это самый эффективный способ, но краткий синтаксис ES6 может выглядеть так:
let arry = [...htmlCollection]
Дополнение: Еще один вариант из комментария Chris_F:
let arry = Array.from(htmlCollection)
Я увидел более лаконичный способ получить методы Array.prototype
, который также работает хорошо. Преобразование объекта HTMLCollection
в объект Array
демонстрируется ниже:
[].slice.call(yourHTMLCollectionObject);
И, как упоминалось в комментариях, для старых браузеров, таких как IE7 и более ранние версии, вам просто нужно использовать функцию совместимости, например:
function toArray(x) {
for (var i = 0, a = []; i < x.length; i++)
a.push(x[i]);
return a;
}
Я знаю, что это старый вопрос, но мне показалось, что принятый ответ немного неполный; поэтому я решил поделиться этим способом, если кому-то это будет полезно.
Этот код работает во всех браузерах, включая более ранние версии Internet Explorer:
var arr = [];
[].push.apply(arr, htmlCollection);
Поскольку jsperf в данный момент недоступен, вот ссылка на jsfiddle, в котором сравнивается производительность различных методов: https://jsfiddle.net/qw9qf48j/
Я предполагаю, что вызов функций Array.prototype
на экземплярах HTMLCollection
является гораздо более эффективным вариантом, чем преобразование коллекций в массивы (например, с помощью [...collection]
или Array.from(collection)
), поскольку в последнем случае коллекция неявно итерируется, и создается новый объект массива, что потребляет дополнительные ресурсы. Функции итерации Array.prototype
можно безопасно вызывать для объектов с последовательными числовыми ключами, начиная с [0]
, и с свойством length
, имеющим корректное числовое значение, равное количеству таких ключей (включая, например, экземпляры HTMLCollection
и FileList
), так что это надежный способ. Также, если подобные операции требуется выполнять часто, можно использовать пустой массив []
для быстрого доступа к функциям Array.prototype
. Вот работающий пример:
alert(
Array.prototype.reduce.call(
document.querySelector('ol').children,
(acc, { textContent }, i) => `${acc}${i + 1}) ${textContent}` + `\n`,
'',
),
);
<ol>
<li>foo</li>
<li>bar</li>
<li>bat</li>
<li>baz</li>
</ol>
Это мое личное решение, основанное на информации из этой темы:
var Divs = new Array();
var Elemns = document.getElementsByClassName("divisao");
try {
Divs = Elemns.prototype.slice.call(Elemns);
} catch(e) {
Divs = $A(Elemns);
}
Где функция $A
была описана Гартом Дэвисом в его посте:
function $A(iterable) {
if (!iterable) return [];
if ('toArray' in Object(iterable)) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
В этом коде я сначала пытаюсь использовать метод slice
для преобразования коллекции Elemns
, полученной с помощью getElementsByClassName
, в массив. Если это не удается — что может произойти в старых браузерах — в качестве резервного варианта использую функцию $A
, которая также может обрабатывать коллекции, поддерживающие длину. Таким образом, мы обеспечиваем кроссбраузерную совместимость.
Проверка наличия ключа в объекте JavaScript?
Как получить доступ к вложенным объектам, массивам или JSON и обработать их?
Как удалить все дубликаты из массива объектов?
Самый эффективный способ группировки массивов объектов
Как очистить массив в JavaScript?