Самый быстрый способ конвертировать JavaScript NodeList в массив?



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



//nl is a NodeList
var arr = Array.prototype.slice.call(nl);


в бенчмаркинге на моем браузере я обнаружил, что это более чем в 3 раза медленнее, чем это:



var arr = [];
for(var i = 0, n; n = nl[i]; ++i) arr.push(n);


они оба производят тот же результат, но мне трудно поверить, что моя вторая версия является самым быстрым возможным способом, тем более люди говорят иначе здесь.



это причуда в моем браузере (Chromium 6)? Или есть более быстрый путь?



EDIT: для тех, кто заботится, я остановился на следующем (который, кажется, самый быстрый в каждом браузере, который я тестировал):



//nl is a NodeList
var l = []; // Will hold the array of Node's
for(var i = 0, ll = nl.length; i != ll; l.push(nl[i++]));


EDIT2: я нашел еще более быстрый способ



// nl is the nodelist
var arr = [];
for(var i = nl.length; i--; arr.unshift(nl[i]));
843   13  

13 ответов:

второй, как правило, быстрее в некоторых браузерах, но главное, что вы должны использовать его, потому что первый из них просто не кросс-браузер. Даже несмотря на то, что времена меняются

@kangax (IE 9 preview)

массив.прототип.кусочек теперь можно конвертировать определенных объектов (например, прописаны в) к массивам-то что большинство современные браузеры были способный сделать довольно долго.

пример:

Array.prototype.slice.call(document.childNodes);

С ES6 теперь у нас есть простой способ создать массив из NodeList: the Array.from()

вот новый классный способ сделать это с помощью ES6 spread operator:

let arr = [...nl];

некоторые оптимизации:

  • сохранить длину списка узлов в переменной
  • явно задать длину массива перед установкой.
  • доступ к индексам, а не толкать или не shifting.

код (см. Этот тест jsperf):

var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
 arr[i] = nl[i];
}

результат будет полностью зависеть от браузера, чтобы дать объективный вердикт, мы должны сделать некоторые тесты, вот результаты, вы можете запустить их здесь:

Chrome 6:

Firefox 3.6:

Firefox 4. 0b2:

Safari 5:

предварительный просмотр платформы IE9 3:

самый быстрый и кросс-браузер

for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);

Как я сравнивал в

http://jsbin.com/oqeda/98/edit

* спасибо @CMS за идею!

Chromium (Similar to Google Chrome)FirefoxOpera

NodeList.prototype.forEach = Array.prototype.forEach;

теперь вы можете сделать документ.querySelectorAll ('div').forEach (функция ()...)

быстрее и короче :

// nl is the nodelist
var a=[], l=nl.length>>>0;
for( ; l--; a[l]=nl[l] );

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

Это функция, которую я использую в моем JS:

function toArray(nl) {
    for(var a=[], l=nl.length; l--; a[l]=nl[l]);
    return a;
}

вот диаграммы, обновленные на дату этой публикации (диаграмма "неизвестная платформа" - Internet Explorer 11.15.16299.0):

Safari 11.1.2Firefox 61.0Chrome 68.0.3440.75Internet Explorer 11.15.16299.0

из этих результатов кажется, что метод preallocate 1 является самой безопасной кросс-браузерной ставкой.

просто быть завершителем здесь, и это быстро тип:

let arr1 = Array.prototype.filter.call(nl, n => true);

let arr2 = Array.prototype.map.call(nl, n => n);

простой способ преобразовать массив-как объекты в массив

nodeList = Array.from(document.querySelectorAll('li'))
// Checking if it's array
Array.isArray(nodeList) // true

Comments

    Ничего не найдено.