Самый быстрый способ конвертировать JavaScript NodeList в массив? - PullRequest
235 голосов
/ 08 июля 2010

В ранее отвеченных вопросах говорилось, что это был самый быстрый способ:

//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)?Или есть более быстрый способ?

РЕДАКТИРОВАТЬ: Для тех, кто заботится, я остановился на следующем (который, кажется, самый быстрый в каждом браузере, который я тестировал):

//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]));

Ответы [ 12 ]

196 голосов
/ 27 марта 2016

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

// nl is a NodeList
let myArray = Array.from(nl)
188 голосов
/ 08 июля 2010

Второй, как правило, работает быстрее в некоторых браузерах, но суть в том, что вы должны использовать его, потому что первый просто не кросс-браузерный.Несмотря на то, что The Times Are a-Changin '

@ kangax ( IE 9 Preview )

Array.prototype.slice теперь может преобразовывать определенные хост-объекты (например, NodeList's) в массивы - то, что большинство современных браузеров могли делать уже довольно давно.1017 *

Пример:

Array.prototype.slice.call(document.childNodes);
95 голосов
/ 20 ноября 2015

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

let arr = [...nl];
19 голосов
/ 09 марта 2011

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

  • сохранить длину NodeList в переменной
  • явно установить длину нового массива перед установкой.
  • получить доступ к индексам вместо нажатияили без сдвига.

Код ( jsPerf ):

var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
 arr[i] = nl[i];
}
15 голосов
/ 08 июля 2010

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

Chrome6:

14 голосов
/ 28 февраля 2013

Самый быстрый и перекрестный браузер - это

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) Firefox Opera

7 голосов
/ 25 декабря 2014
NodeList.prototype.forEach = Array.prototype.forEach;

Теперь вы можете сделать document.querySelectorAll ('div'). ForEach (function () ...)

5 голосов
/ 22 января 2013

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

// nl is the nodelist
var a=[], l=nl.length>>>0;
for( ; l--; a[l]=nl[l] );
3 голосов
/ 26 февраля 2019

В ES6 вы можете использовать:

  • Array.from

    let array = Array.from(nodelist)

  • Оператор спреда

    let array = [...nodelist]

3 голосов
/ 08 марта 2013

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

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