Maneira mais eficiente para converter um HTMLCollection para uma matriz

Existe uma maneira mais eficiente para converter um HTMLCollection para uma matriz, além de percorrer o conteúdo da coleção e empurrando manualmente cada item em uma matriz?

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

terá o mesmo efeito usando o código “nativo”.

Editar

Como isso recebe muitas visualizações, observe (per @ oriol’s comment) que a seguinte expressão mais concisa é efetivamente equivalente:

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

Mas note que o comentário de @JussiR, que ao contrário do formulário “detalhado”, cria uma instância de matriz vazia, não usada e de fato inutilizável no processo. O que os compiladores fazem sobre isso está fora do ken do programador.

Editar

Desde ECMAScript 2015 (ed 6), há também Array.from :

 var arr = Array.from(htmlCollection); 

Não tenho certeza se isso é o mais eficiente, mas uma syntax concisa do ES6 pode ser:

 let arry = [...htmlCollection] 

Edit: Outro, de Chris_F comentário:

 let arry = Array.from(htmlCollection) 

Eu vi um método mais conciso de obter methods Array.prototype em geral que funciona tão bem. A conversão de um object HTMLCollection em um object Array é demonstrada abaixo:

 [] .slice.call (yourHTMLCollectionObject);

E, como mencionado nos comentários, para navegadores antigos, como o IE7 e versões anteriores, você simplesmente tem que usar uma function de compatibilidade, como:

 function toArray(x) { for(var i = 0, a = []; i < x.length; i++) a.push(x[i]); return a } 

Eu sei que esta é uma pergunta antiga, mas senti que a resposta aceita era um pouco incompleta; então eu pensei em jogar isso lá fora FWIW.

Para uma implementação cross-browser, sugiro que você olhe para a function prototype.js $A

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

Ele não usa o Array.prototype.slice provavelmente porque não está disponível em todos os navegadores. Eu tenho medo que o desempenho seja muito ruim, pois há um loop de javascript sobre o iterable .

Isso funciona em todos os navegadores, incluindo versões anteriores do IE.

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

Como o jsperf ainda está inativo no momento, aqui está um jsfiddle que compara o desempenho de diferentes methods. https://jsfiddle.net/qw9qf48j/

Esta é a minha solução pessoal, baseada nas informações aqui (este tópico):

 var Divs = new Array(); var Elemns = document.getElementsByClassName("divisao"); try { Divs = Elemns.prototype.slice.call(Elemns); } catch(e) { Divs = $A(Elemns); } 

Onde $ A foi descrito por Gareth Davis em seu 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; } 

Se o navegador suportar a melhor maneira, ok, caso contrário, usará o cross browser.

Para converter array-like para array de maneira eficiente, podemos fazer uso do jQuery makeArray :

makeArray: Converta um object do tipo array em um array JavaScript verdadeiro.

Uso:

 var domArray = jQuery.makeArray(htmlCollection); 

Um pouco extra:

Se você não quiser manter a referência ao object de matriz (na maioria das vezes, as alterações de HTMLC são dinamicamente alteradas, então é melhor copiá-las para outro array. Este exemplo presta muita atenção ao desempenho:

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

O que é um array?

HTMLCollection é um object "array-like" , os objects do tipo array são similares ao object do array, mas faltam muitas definições funcionais:

Objetos semelhantes a matrizes parecem matrizes. Eles possuem vários elementos numerados e uma propriedade length. Mas é aí que a semelhança pára. Objetos semelhantes a matrizes não possuem nenhuma das funções da Matriz, e os loops for-in nem funcionam!