Eu queria saber, o JavaScript oferece uma variedade de métodos para obter o primeiro elemento filho de qualquer elemento, mas qual é o melhor? Pelo melhor, quero dizer: mais compatível com vários navegadores, mais rápido, mais abrangente e previsível quando se trata de comportamento. Uma lista de métodos / propriedades que eu uso como alias:
var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]
Isso funciona para os dois casos:
var child = elem.childNodes[0]; // or childNodes[1], see below
Isso é no caso de formulários ou <div>
iteração. Se eu encontrar elementos de texto:
var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;
Tanto quanto eu posso trabalhar, firstChild
usa o NodeList de childNodes
, e firstElementChild
usa children
. Estou baseando essa suposição na referência MDN:
childNode
é uma referência ao primeiro elemento filho do nó do elemento ounull
se não houver um.
Eu estou supondo que, em termos de velocidade, a diferença, se houver, será quase nula, já que firstElementChild
é efetivamente uma referência children[0]
e o children
objeto já está na memória de qualquer maneira.
O que me joga, é o childNodes
objeto. Eu usei para dar uma olhada em um formulário, em um elemento de tabela. Enquanto children
lista todos os elementos do formulário, childNodes
também parece incluir espaço em branco no código HTML:
console.log(elem.childNodes[0]);
console.log(elem.firstChild);
Ambos log <TextNode textContent="\n ">
console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);
Todos os log <input type="text"
... >
. Por quê? Eu entenderia que um objeto me permitiria trabalhar com o código HTML "bruto", enquanto o outro adere ao DOM, mas o childNodes
elemento parece funcionar nos dois níveis.
Para voltar à minha pergunta inicial, meu palpite seria: se eu quero o objeto mais abrangente, childNodes
é o caminho a percorrer, mas, devido à sua abrangência, pode não ser o mais previsível em termos de retorno do elemento que eu quero / esperar a qualquer momento. O suporte a vários navegadores também pode ser um desafio nesse caso, embora eu possa estar errado.
Alguém poderia esclarecer a distinção entre os objetos em questão? Se houver uma diferença de velocidade, ainda que insignificante, eu também gostaria de saber. Se eu estiver vendo tudo errado, sinta-se à vontade para me educar.
PS: Por favor, por favor, eu gosto de JavaScript, então sim, quero lidar com esse tipo de coisa. Respostas como "o jQuery lida com isso para você" não são o que estou procurando, portanto, nãojquery tag.
fonte
Respostas:
Parece que você está pensando demais. Você observou a diferença entre
childNodes
echildren
, quechildNodes
contém todos os nós, incluindo os nós de texto que consistem inteiramente em espaço em branco, enquantochildren
é uma coleção apenas dos nós filhos que são elementos. Isso é realmente tudo o que existe.Não há nada imprevisível em nenhuma das coleções, embora haja alguns problemas a serem observados:
childNodes
enquanto outros navegadoreschildren
enquanto outros navegadores têm apenas elementoschildren
,firstElementChild
e amigos são apenas conveniências, apresentando uma exibição filtrada do DOM restrita a apenas elementos.fonte
<td\n\t>content</td>
. Como você pode fazer com o XML, para evitar que o espaço em branco em excesso seja considerado parte dos dados (ou DOM, nesse caso). Por que espaço em branco dentro de uma tag seria incluído no DOM?children
originou no IE 4 mais de uma década antes de se tornar um padrão ou ser adotado por outros navegadores, você poderia argumentar que o IE <= 8 está correto e outros navegadores estão errados.firstElementChild pode não estar disponível no IE <9 (apenas firstChild)
no IE <9 firstChild é o firstElementChild porque o MS DOM (IE <9) não está armazenando nós de texto vazios. Mas se você fizer isso em outros navegadores, eles retornarão nós de texto vazios ...
minha solução
child=(elem.firstElementChild||elem.firstChild)
isso dará o primeiro filho mesmo no IE <9
fonte
elem.firstChild
não for um nó de elemento, os resultados serão diferentes nos IEs antigos, porqueelem.firstElementChild
é sempre o nó do elemento.firstElementChild
também não é necessariamente seguro em navegadores que não sejam o IE: o Firefox só começou a suportá-lo na versão 3.5.A maneira de fazer vários navegadores é usar
childNodes
para obterNodeList
e criar uma matriz de todos os nós comnodeType
ELEMENT_NODE .http://jsfiddle.net/s4kxnahu/
Isso é especialmente fácil se você estiver usando uma biblioteca de utilitários como o lodash :
Futuro:
Você pode usar
querySelectorAll
em combinação com a:scope
pseudo-classe (corresponde ao elemento que é o ponto de referência do seletor):No momento da redação deste artigo, isso
:scope
é suportado no Chrome, Firefox e Safari.fonte
Apenas para adicionar outras respostas, ainda existem diferenças notáveis aqui, especificamente ao lidar com
<svg>
elementos.Eu usei ambos
.childNodes
e.children
preferi trabalhar com osHTMLCollection
entregues pelo.children
getter.Hoje, no entanto, tive problemas com o IE / Edge com falha ao usar
.children
um<svg>
. Embora.children
seja suportado no IE em elementos HTML básicos, ele não é suportado em fragmentos de documento / documento ou elementos SVG .Para mim, eu pude simplesmente pegar os elementos necessários,
.childNodes[n]
porque não tenho nós de texto estranhos para me preocupar. Você pode fazer o mesmo, mas, como mencionado acima, não se esqueça de que pode encontrar elementos inesperados.Espero que isso seja útil para alguém coçando a cabeça tentando descobrir por que
.children
funciona em outros lugares em seus js no IE moderno e falha nos elementos de documento ou SVG.fonte
Ei, pessoal, não deixe o espaço em branco te enganar. basta testar isso em um navegador de console. use javascript nativo. Aqui está e exemplo com dois conjuntos 'ul' com a mesma classe. Você não precisa ter sua lista 'ul' em uma linha para evitar o espaço em branco; basta usar a contagem de matrizes para pular o espaço em branco.
Como chegar espaço em torno branco com
querySelector()
entãochildNodes[]
js ligação violino: https://jsfiddle.net/aparadise/56njekdo/fonte
document.querySelector
não foi bem apoiada na época. b) A questão é basicamente perguntar quais são as diferenças entrechildren
echildNodes
internamente , o que é mais confiável, quando escolher uma sobre a outra. e c) Porque, como demonstrada em questão:childNodes
não incluem espaços em branco nós,children
não ...