Самый быстрый способ конвертировать JavaScript NodeList в Array?
ранее ответил на вопросы здесь сказал, что это был самый быстрый способ:
//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]));
13 ответов
второй, как правило, быстрее в некоторых браузерах, но главное, что вы должны использовать его, потому что первый просто не кросс-браузер. Хотя времена меняются!--2-->
@kangax (IE 9 предварительный просмотр)
массив.прототип.ломтик теперь можно конвертировать некоторые объекты хоста (например, NodeList) к массивам-то, что большинство современные браузеры были уметь делать довольно долго.
пример:
Array.prototype.slice.call(document.childNodes);
С ES6 теперь у нас есть простой способ создать массив из списка узлов:Array.from()
вот новый классный способ сделать это с помощью ES6 оператор распространения:
let arr = [...nl];
некоторые оптимизации:
- сохранить длину NodeList в переменной
- явно задать длину массива перед установкой.
- доступ к индексам, а не подталкивание или ... непоколебимой.
код (см. Этот тест 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:
платформа ИЕ9 просмотра 3:
самый быстрый и кросс-браузер
for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);
Как я сравнивал в
http://jsbin.com/oqeda/98/edit
* спасибо @CMS за идею!
NodeList.prototype.forEach = Array.prototype.forEach;
теперь вы можете сделать документ.querySelectorAll ('div').forEach (функция ()...)
проверить это сообщение в блоге здесь это говорит об одном и том же. Насколько я понимаю, дополнительное время может быть связано с продвижением по цепочке прицела.
Это функция, которую я использую в своем JS:
function toArray(nl) {
for(var a=[], l=nl.length; l--; a[l]=nl[l]);
return a;
}
вот диаграммы, обновленные на дату этой публикации (диаграмма "неизвестная платформа" - Internet 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