Isso me incomoda que eu não consigo fazer apenas document.querySelectorAll(...).map(...)
no Firefox 3.6, e ainda não consigo encontrar uma resposta, então pensei em fazer uma postagem cruzada no SO a pergunta deste blog:
http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/
Alguém sabe de um motivo técnico pelo qual você não consegue um Array? Ou por um StaticNodeList não herda de uma matriz de tal forma a que você poderia usar map
, concat
, etc?
(Aliás, se for apenas uma função que você deseja, você pode fazer algo como NodeList.prototype.map = Array.prototype.map;
... mas, novamente, por que essa funcionalidade (intencionalmente?) Está bloqueada em primeiro lugar?)
Respostas:
Acredito que seja uma decisão filosófica do W3C. O design do W3C DOM [spec] é bastante ortogonal ao design do JavaScript, pois o DOM deve ser neutro em relação à plataforma e à linguagem.
Decisões como "
getElementsByFoo()
retorna um ordenadoNodeList
" ou "querySelectorAll()
retorna umStaticNodeList
" são muito intencionais, de modo que as implementações não precisam se preocupar em alinhar sua estrutura de dados retornada com base em implementações dependentes de linguagem (como.map
estar disponível em Arrays em JavaScript e Ruby, mas não em listas em C #).O objetivo do W3C é baixo: eles dirão que a
NodeList
deve conter uma propriedade somente leitura.length
do tipo unsigned long porque acreditam que cada implementação pode pelo menos suportar isso , mas não dirão explicitamente que o[]
operador de índice deve ser sobrecarregado para suportar a obtenção de elementos posicionais, porque eles não querem bloquear uma pequena linguagem pobre que surge e que deseja implementar,getElementsByFoo()
mas não pode suportar a sobrecarga do operador. É uma filosofia predominante presente em grande parte das especificações.John Resig expressou uma opção semelhante à sua, à qual acrescenta :
Eu empatia um pouco. Se o DOM fosse escrito especificamente com recursos JavaScript em mente, seria muito menos complicado e mais intuitivo de usar. Ao mesmo tempo, eu entendo as decisões de design do W3C.
fonte
StaticNodeList
para um array. Eu endossaria a resposta de @ mck89 como o caminho a seguir para converter umNodeList
/StaticNodeList
para um Array nativo, mas isso irá falhar no IE (óbvio 8) com um erro de JScript, uma vez que esses objetos são hospedados / "especiais".document
,window
etc. O IE geralmente implementa esses "especialmente" (por exemplo, como objetos COM) que às vezes não se conformam ao uso normal, de maneiras pequenas e sutis, comoArray.prototype.slice.call
bombardeio quando dado aStaticNodeList
;)Você pode usar o operador de propagação ES2015 (ES6) :
[...document.querySelectorAll('div')]
irá converter StaticNodeList em Array de itens.
Aqui está um exemplo de como usá-lo.
fonte
Array.from(document.querySelectorAll('div')).map(x => console.log(x.innerHTML))
Não sei por que ele retorna uma lista de nós em vez de uma matriz, talvez porque, como getElementsByTagName, ele atualizará o resultado quando você atualizar o DOM. De qualquer forma, um método muito simples para transformar esse resultado em uma matriz simples é:
e então você pode fazer:
fonte
slice
linha embora.Só para acrescentar ao que Crescent disse,
Não faça isso! Não é garantido que funcione.
Nenhum padrão JavaScript ou DOM / BOM especifica que a
NodeList
função construtora existe mesmo como umawindow
propriedade / global , ou que oNodeList
retornado porquerySelectorAll
herdará dela, ou que seu protótipo é gravável, ou que a funçãoArray.prototype.map
realmente funcionará em um NodeList.Um NodeList pode ser um 'objeto host' (e é um, no IE e em alguns navegadores mais antigos). Os
Array
métodos são definidos como tendo permissão para operar em qualquer 'objeto nativo' de JavaScript que exponha numéricos elength
propriedades, mas eles não são obrigados a funcionar em objetos de host (e no IE, eles não funcionam).É irritante que você não obtenha todos os métodos de array nas listas DOM (todos eles, não apenas StaticNodeList), mas não há uma maneira confiável de contornar isso. Você terá que converter cada lista DOM que retornar em um Array manualmente:
fonte
new Array(n)
apenas dá ao terp JS uma dica de quanto tempo o array vai acabar. Isso poderia permitir que ele alocasse essa quantidade de espaço com antecedência, o que poderia potencialmente resultar em um aumento de velocidade, já que algumas realocações de memória poderiam ser evitadas conforme o array cresce. Não sei se isso realmente ajuda em navegadores modernos ... Eu suspeito que não seja mensurável.Eu acho que você pode simplesmente seguir
Funciona perfeito para mim
fonte
Esta é uma opção que eu gostaria de acrescentar ao leque de outras possibilidades sugeridas por outros aqui. Destina-se apenas à diversão intelectual e não é aconselhável .
Só por diversão , aqui está uma maneira de "forçar"
querySelectorAll
a se ajoelhar e se curvar diante de você:Agora é bom passar por cima dessa função, mostrando quem manda. Agora eu não sei o que é melhor, criar um novo wrapper de função nomeada e, em seguida, fazer com que todo o seu código use aquele nome estranho (quase no estilo jQuery) ou sobrescreva a função como acima uma vez para que o resto do seu código ainda seja capaz para usar o nome do método DOM original
querySelectorAll
.fonte