it-swarm.com.ru

Самый эффективный способ конвертировать HTMLCollection в массив

Есть ли более эффективный способ преобразовать HTMLCollection в массив, кроме как перебирать содержимое указанной коллекции и вручную помещать каждый элемент в массив?

298
Tom
var arr = Array.prototype.slice.call( htmlCollection )

будет иметь тот же эффект, используя "родной" код.

Редактировать

Так как это получает много просмотров, обратите внимание (на комментарий @ oriol), что следующее более краткое выражение эффективно эквивалентно:

var arr = [].slice.call(htmlCollection);

Но обратите внимание на комментарий @ JussiR, который, в отличие от "многословной" формы, создает в процессе пустой, неиспользуемый и действительно неиспользуемый экземпляр массива. То, что компиляторы делают с этим, находится за пределами возможностей программиста.

Редактировать

Начиная с ECMAScript 2015 (редакция 6) также есть Array.from :

var arr = Array.from(htmlCollection);

Редактировать

ECMAScript 2015 также предоставляет оператор распространения , который функционально эквивалентен Array.from (хотя обратите внимание, что Array.from поддерживает функцию отображения в качестве второго аргумента).

var arr = [...htmlCollection];

Я подтвердил, что оба из вышеперечисленных работают на NodeList.

538
harpo

не уверен, что это наиболее эффективно, но краткий синтаксис ES6 может быть таким:

let arry = [...htmlCollection] 

Правка: еще один, из комментария Chris_F:

let arry = Array.from(htmlCollection)
76
mido

Я видел более краткий метод получения методов 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
}

Я знаю, что это старый вопрос, но я чувствовал, что принятый ответ был немного неполным; так что я решил выбросить это туда, FWIW.

19
Codesmith

Для кросс-браузерной реализации я бы предложил посмотреть на функцию prototype.js$A

скопировано из 1.6.1 :

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

Он не использует Array.prototype.slice, вероятно, потому что он доступен не во всех браузерах. Я боюсь, что производительность довольно плохая, так как откат назад - цикл javascript над iterable.

6
Gareth Davis

Это мое личное решение, основанное на информации здесь (эта тема):

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

Если браузер поддерживает лучший способ, хорошо, иначе будет использовать кросс-браузер.

3
Gustavo

Это работает во всех браузерах, включая более ранние версии IE.

var arr = [];
[].Push.apply(arr, htmlCollection);

Поскольку jsperf все еще не работает в данный момент, вот jsfiddle, который сравнивает производительность различных методов. https://jsfiddle.net/qw9qf48j/

3
Nicholas

Для эффективного преобразования массива в массив мы можем использовать jQuerymakeArray:

makeArray: конвертировать массивоподобный объект в истинный массив JavaScript.

Использование:

var domArray = jQuery.makeArray(htmlCollection);

Немного больше:

Если вы не хотите сохранять ссылку на объект массива (большую часть времени HTMLCollections динамически изменяется, поэтому лучше скопировать их в другой массив, в этом примере обратите особое внимание на производительность:

var domDataLength = domData.length //Better performance, no need to calculate every iteration the domArray length
var resultArray = new Array(domDataLength) // Since we know the length its improves the performance to declare the result array from the beginning.

for (var i = 0 ; i < domDataLength ; i++) {
    resultArray[i] = domArray[i]; //Since we already declared the resultArray we can not make use of the more expensive Push method.
}

Что такое массив?

HTMLCollection - это объект "array-like", объекты как в массиве похожи на объект массива, но в нем отсутствует большая часть его функционального определения:

Подобные массиву объекты выглядят как массивы. Они имеют различные пронумерованные элементы и свойство длины. Но на этом сходство заканчивается. Подобные массиву объекты не имеют никаких функций Array, и циклы for-in даже не работают!

1
Shahar Shokrani