JavaScript Buscando: getElement*, querySelector*
Explore e domine o Document Object Model (DOM) com os métodos getElement* e querySelector* do JavaScript para criar aplicações web interativas.
Antes de alterar, mover ou ler qualquer coisa em uma página, você precisa encontrar o elemento desejado. Este é o primeiro passo de praticamente toda tarefa com o DOM, e o JavaScript oferece duas famílias de ferramentas para isso:
- Métodos legados
getElement*—getElementById,getElementsByClassName,getElementsByTagName. São rápidos e retornam coleções dinâmicas. - Métodos modernos
querySelector*—querySelector,querySelectorAll. Aceitam qualquer seletor CSS e retornam resultados estáticos.
Este guia aborda as duas famílias, os auxiliares matches, closest e contains para verificar e percorrer a árvore, e a principal armadilha: a diferença entre uma coleção dinâmica e uma estática. Cada exemplo é executável, para que você veja o resultado imediatamente.
Depois de encontrar um elemento, os próximos passos geralmente são percorrer o DOM para acessar seus vizinhos e manipular o DOM para modificá-lo. Para uma visão geral mais introdutória, consulte selecionando elementos DOM.
Acesso Eficiente a Elementos: getElementById
O método getElementById é a forma mais rápida e confiável de acessar um único elemento, pois um ID deve ser único dentro de um documento e os navegadores indexam IDs internamente. Ele retorna o elemento correspondente, ou null se nenhum elemento com esse ID existir — portanto, verifique se o resultado não é null antes de utilizá-lo. Note que você passa o ID diretamente, sem o # inicial (isso é usado apenas em seletores CSS). No exemplo abaixo, o texto inicial "Default text" é substituído imediatamente.
<!-- snippet: html-result -->
<!DOCTYPE html>
<html>
<head>
<title>getElementById Example</title>
</head>
<body>
<div id="main-content">Default text</div>
<script>
const element = document.getElementById('main-content');
element.innerHTML = "Modified text!"
</script>
</body>
</html>Acessando Múltiplos Elementos: getElementsByClassName e getElementsByTagName
Quando você seleciona elementos pelo nome de classe ou nome de tag, obtém de volta um HTMLCollection. Esta é uma coleção dinâmica: ela se atualiza automaticamente conforme o DOM muda. É semelhante a um array — você pode acessar elementos pelo índice (els[0]) e verificar els.length — mas não é um array real, portanto não tem forEach, map ou filter. Para iterá-la com segurança, converta-a primeiro com Array.from(...) (ou o spread [...els]).
Exemplo Usando getElementsByClassName
Acesse múltiplos elementos com a mesma classe usando getElementsByClassName. Neste exemplo, temos dois elementos div com o mesmo nome de classe. Modificamos ambos selecionando-os pelo nome de classe.
<!-- snippet: html-result -->
<!DOCTYPE html>
<html>
<head>
<title>getElementsByClassName Example</title>
</head>
<body>
<div class="info">First Info</div>
<div class="info">Second Info</div>
<script>
const infoElements = document.getElementsByClassName('info');
Array.from(infoElements).forEach(el => el.innerHTML = "MODIFIED!");
</script>
</body>
</html>Exemplo Usando getElementsByTagName
Recupere elementos pelo nome da tag com getElementsByTagName. É completamente similar ao exemplo anterior, mas desta vez selecionamos pelo nome da tag, e não pelo nome de classe.
<!-- snippet: html-result -->
<!DOCTYPE html>
<html>
<head>
<title>getElementsByTagName Example</title>
</head>
<body>
<p>First Paragraph</p>
<p>Second Paragraph</p>
<script>
const paragraphs = document.getElementsByTagName('p');
Array.from(paragraphs).forEach(el => el.innerHTML = "MODIFIED!");
</script>
</body>
</html>Buscas Flexíveis com querySelector e querySelectorAll
Selecionando com querySelector
Use querySelector para encontrar o primeiro elemento que corresponde a um seletor CSS. Neste exemplo, selecionamos o primeiro elemento com a classe text que é filho direto do elemento com o id main.
<!-- snippet: html-result -->
<!DOCTYPE html>
<html>
<head>
<title>QuerySelector Example</title>
</head>
<body>
<div id="main"><span class="text">This will be replaced</span></div>
<div id="other"><span class="text">This one doesn't change</span></div>
<script>
const spanInsideDiv = document.querySelector('#main > .text');
spanInsideDiv.innerHTML = "MODIFIED!";
</script>
</body>
</html>Recuperando Múltiplos Elementos com querySelectorAll
querySelectorAll retorna todos os elementos que correspondem a um seletor CSS, como uma NodeList estática. Convenientemente, uma NodeList possui um forEach integrado, então você pode iterar sobre ela diretamente sem precisar converter para um array.
A palavra estática é importante: querySelectorAll tira um instantâneo das correspondências no momento em que você o chama. Se você adicionar ou remover elementos correspondentes posteriormente, esse instantâneo não será alterado. Isso é exatamente o oposto da HTMLCollection dinâmica retornada pelos métodos getElementsBy*.
<!-- snippet: html-result -->
<!DOCTYPE html>
<html>
<head>
<title>QuerySelectorAll Example</title>
</head>
<body>
<ul>
<li class="item">Item 1</li>
<li class="item">Item 2</li>
</ul>
<script>
const items = document.querySelectorAll('.item');
items.forEach(item => item.innerHTML = "MODIFIED!");
</script>
</body>
</html>Dinâmico vs. Estático: a Armadilha das Coleções
Esta é a armadilha que pega a maioria dos iniciantes. Uma HTMLCollection dinâmica reflete o estado atual do DOM a cada leitura, enquanto uma NodeList estática fica congelada no momento da seleção. O trecho abaixo mostra ambas reagindo a um elemento recém-adicionado:
// Suppose the page has two <li class="item"> elements.
const live = document.getElementsByClassName('item'); // live HTMLCollection
const snapshot = document.querySelectorAll('.item'); // static NodeList
console.log(live.length); // 2
console.log(snapshot.length); // 2
// Now add a third matching element.
const li = document.createElement('li');
li.className = 'item';
document.querySelector('ul').appendChild(li);
console.log(live.length); // 3 — updated automatically
console.log(snapshot.length); // 2 — still the old snapshotPor que isso importa: iterar sobre uma coleção dinâmica enquanto remove elementos correspondentes é uma fonte clássica de itens ignorados, pois a coleção diminui durante a iteração. Uma NodeList estática de querySelectorAll é mais segura nesse caso, pois a lista não mudará durante o loop.
Verificando e Percorrendo: matches, closest e contains
Buscar não é apenas encontrar elementos — muitas vezes você tem um elemento e precisa fazer uma pergunta sobre ele.
element.matches(selector)retornatruese o próprio elemento corresponde ao seletor CSS. Ótimo para delegação de eventos.element.closest(selector)percorre para cima na árvore a partir do elemento (incluindo ele mesmo) e retorna o ancestral mais próximo que corresponde, ounull.parent.contains(node)retornatruesenodeé o próprio pai ou um descendente dele.
<!-- snippet: html-result -->
<!DOCTYPE html>
<html>
<body>
<section class="card">
<button id="save" class="btn primary">Save</button>
</section>
<div id="out"></div>
<script>
const btn = document.getElementById('save');
const section = document.querySelector('.card');
const out = document.getElementById('out');
out.innerHTML =
'matches(".primary"): ' + btn.matches('.primary') + '<br>' +
'closest(".card") is section: ' + (btn.closest('.card') === section) + '<br>' +
'section.contains(btn): ' + section.contains(btn);
</script>
</body>
</html>Qual Método Devo Usar?
- Precisa de um elemento pelo ID? Use
getElementById— é o mais rápido e mais claro. - Precisa de um seletor CSS (descendentes, combinadores, atributos,
:not())? UsequerySelector/querySelectorAll. - Precisa de uma lista dinâmica que acompanhe as mudanças no DOM? Use
getElementsByClassName/getElementsByTagName. - Tem um elemento e precisa testar ou percorrer a árvore? Use
matches,closestoucontains.
Conclusão
Encontrar elementos é a base de todo script DOM. Recorra ao getElementById para IDs únicos, ao querySelector* pela flexibilidade dos seletores CSS, e aos métodos getElementsBy* quando você realmente precisar de uma coleção dinâmica — apenas lembre-se da diferença entre dinâmico e estático para que as coleções não o surpreendam no meio de um loop. A partir daqui, continue com percorrendo o DOM e manipulação do DOM.