javascript - La forma más eficiente de convertir un HTMLCollection en un Array
htmlcollection to array (7)
Esta es mi solución personal, basada en la información aquí (este hilo):
var Divs = new Array();
var Elemns = document.getElementsByClassName("divisao");
try {
Divs = Elemns.prototype.slice.call(Elemns);
} catch(e) {
Divs = $A(Elemns);
}
Donde $ A fue descrito por Gareth Davis en su post:
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;
}
Si el navegador es compatible con la mejor manera, está bien, de lo contrario utilizará el navegador cruzado
¿Existe una forma más eficiente de convertir una colección HTMLC en una matriz, aparte de iterar el contenido de dicha colección y empujar manualmente cada elemento en una matriz?
Esto funciona en todos los navegadores, incluidas las versiones anteriores de IE.
var arr = [];
[].push.apply(arr, htmlCollection);
Como jsperf aún está inactivo en este momento, aquí hay un jsfiddle que compara el rendimiento de diferentes métodos. https://jsfiddle.net/qw9qf48j/
No estoy seguro de si esto es lo más eficiente, pero una sintaxis ES6 concisa podría ser:
let arry = [...htmlCollection]
Edit: Otro, desde el comentario de Chris_F:
let arry = Array.from(htmlCollection)
Para convertir array-like a array de forma eficiente, podemos hacer uso de jQuery makeArray
:
makeArray: Convierte un objeto similar a una matriz en una verdadera matriz de JavaScript.
Uso:
var domArray = jQuery.makeArray(htmlCollection);
Un poco más:
Si no desea mantener la referencia al objeto de la matriz (la mayoría de las veces, HTMLCollections cambia dinámicamente, por lo que es mejor copiarlas en otra matriz.
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.
}
¿Qué es una matriz?
jQuery es un objeto "array-like"
similar a una "array-like"
, los objetos similares a una matriz son similares a los objetos de la matriz pero faltan muchas de sus definiciones funcionales:
Los objetos similares a matrices se ven como matrices. Tienen varios elementos numerados y una propiedad de longitud. Pero ahí es donde la similitud se detiene. Los objetos de tipo Array no tienen ninguna de las funciones de Array, ¡y los bucles de entrada no funcionan!
Para una implementación de navegador cruzado, le sugiero que vea la función prototype.js $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;
}
Probablemente no use Array.prototype.slice
porque no está disponible en todos los navegadores. Me temo que el rendimiento es bastante malo, ya que la caída es un bucle de javascript sobre el iterable
.
Vi un método más conciso para obtener métodos de Array.prototype
en general que funcionan igual de bien. A continuación se HTMLCollection
convertir un objeto HTMLCollection
en un objeto Array
:
[].slice.call( yourHTMLCollectionObject );
Y, como se mencionó en los comentarios, para los navegadores antiguos como IE7 y anteriores, simplemente tiene que usar una función de compatibilidad, como:
function toArray(x) {
for(var i = 0, a = []; i < x.length; i++)
a.push(x[i]);
return a
}
Sé que esta es una pregunta antigua, pero sentí que la respuesta aceptada estaba un poco incompleta; así que pensé en tirar esto por ahí FWIW.
var arr = Array.prototype.slice.call( htmlCollection )
Tendrá el mismo efecto utilizando el código "nativo".
Editar
Dado que esto obtiene muchas vistas, tenga en cuenta (según el comentario de @oriol) que la siguiente expresión más concisa es efectivamente equivalente:
var arr = [].slice.call(htmlCollection);
Pero tenga en cuenta el comentario de @ JussiR, que a diferencia del formulario "detallado", crea una instancia de matriz vacía, no utilizada y, de hecho, inutilizable en el proceso. Lo que hacen los compiladores al respecto está fuera del alcance del programador.
Editar
Desde ECMAScript 2015 (ed 6) también hay Array.from .
var arr = Array.from(htmlCollection);
Editar
ECMAScript 2015 también proporciona el operador de dispersión , que es funcionalmente equivalente a Array.from
(aunque tenga en cuenta que Array.from
admite una función de mapeo como segundo argumento).
var arr = [...htmlCollection];
He confirmado que ambos de los trabajos anteriores en NodeList
.