Eu me deparei com este atalho puro para converter um DOM NodeList em uma matriz regular, mas devo admitir que não entendo completamente como ele funciona:
[].slice.call(document.querySelectorAll('a'), 0)
Então começa com uma matriz vazia []
, depois slice
é usada para converter o resultado de call
uma nova matriz, sim?
O pouco que eu não entendo é o call
. Como isso converte document.querySelectorAll('a')
de um NodeList para uma matriz regular?
javascript
arrays
call
slice
Yansky
fonte
fonte
Array.prototype.slice.call(document.querySelectorAll('a'));
é uma maneira adequada de escrever o pedaço de código que você escreveu.Array.from
. Então, por exemplo, isso faria o mesmo: Array.from (document.querySelectorAll ('a'));Respostas:
O que está acontecendo aqui é que você chama
slice()
como se fosse uma função doNodeList
usocall()
. O queslice()
faz neste caso é criar uma matriz vazia, então iterate através do objeto que está sendo executado (originalmente um array, agora umNodeList
) e mantê acrescentando os elementos desse objeto para a matriz vazia que criou, que é finalmente voltou. Aqui está um artigo sobre isso .EDITAR:
Isso não está certo.
[].slice
retorna um objeto de função. Um objeto de função possui uma funçãocall()
que chama a função que atribui o primeiro parâmetro docall()
parathis
; em outras palavras, fazer com que a função pense que está sendo chamada do parâmetro (NodeList
retornado pordocument.querySelectorAll('a')
) e não de uma matriz.fonte
Array.prototype.slice.call(...)
, ele na verdade instancia um objeto de matriz ([]
) apenas para acessar seu método de fatia de protótipo. Essa é uma instanciação perdida. Dizer, aoArray.prototype.slice.call(...)
contrário, é mais limpo, embora você adicione vários caracteres ao seu JS se estiver contando ...NodeList
s[]
é mais confiável, poisArray
pode ser substituído por outra coisa. Se você precisar reutilizarArray#slice
, é uma boa ideia armazená-lo em cache.var array = []; var push = array.push; var slice = array.slice; var splice = array.splice;
ele faz isso pela questão de segurança que @MathiasBynens menciona?Em JavaScript, os métodos de um objeto podem ser vinculados a outro objeto em tempo de execução. Em resumo, o javascript permite que um objeto "empreste" o método de outro objeto:
Os métodos
call
eapply
dos objetos de função (em JavaScript, as funções também são objetos) permitem fazer isso. Portanto, no seu código, você poderia dizer que o NodeList está emprestando o método de fatia de uma matriz..slice()
retorna outra matriz como resultado, que se tornará a matriz "convertida" que você poderá usar.fonte
call
função deArray.prototype
aka[].prototype
você mesmo.Ele recupera a
slice
função de umArray
. Em seguida, chama essa função, mas usando o resultado dedocument.querySelectorAll
como othis
objeto em vez de uma matriz real.fonte
É uma técnica para converter objetos do tipo matriz em matrizes reais.
Alguns desses objetos incluem:
arguments
em funçõesIsso serve para muitos propósitos, por exemplo, objetos são passados por referência, enquanto matrizes são passadas por valor.
Além disso, observe que o primeiro argumento
0
pode ser omitido, explicação completa aqui .E por uma questão de integridade, também há jQuery.makeArray () .
fonte
Este é o código que temos,
Vamos desmontá-lo primeiro,
Etapa: 1 Execução da
call
funçãocall
, além dothisArg
, o restante dos argumentos será anexado a uma lista de argumentos.slice
será invocada vinculando seuthis
valor comothisArg
(o objeto semelhante ao array veiodocument.querySelector
) e com a lista de argumentos. ie] argumentostart
que contém0
Etapa: 2 Execução da
slice
função chamada dentro docall
start
será atribuído a uma variávels
como0
end
sejaundefined
,this.length
será armazenado eme
a
Depois de fazer as configurações acima, a seguinte iteração ocorrerá
a
será retornada como resultado.PS Para uma melhor compreensão do nosso cenário, algumas etapas necessárias para o nosso contexto foram ignoradas no algoritmo original de chamada e fatia .
fonte
fonte
No ES6: Simplesmente crie um array com Array.from (element.children) ou Array.from ({length: 5})
fonte