firstChild, lastChild, nextSibling

firstChild, lastChild, nextSibling, previousSibling — свойства интерфейса Node, возвращающие соседние и дочерние узлы DOM-дерева включая текстовые узлы и комментарии.

Зачем нужно

Эти свойства дают низкоуровневый доступ ко всем узлам дерева, включая текстовые (пробелы, переводы строк). Важно отличать их от firstElementChild, lastElementChild и nextElementSibling, которые возвращают только узлы-элементы (Element) и используются значительно чаще в практической работе.

Где используется

  • Обход DOM-дерева для поиска узлов
  • Работа с текстовыми узлами напрямую
  • Низкоуровневые манипуляции при реализации парсеров/рендереров
  • Итерация по соседним элементам

Node vs Element свойства

Node свойство Element аналог Возвращает
firstChild firstElementChild Node (любой тип) / Element
lastChild lastElementChild Node / Element
nextSibling nextElementSibling Node / Element
previousSibling previousElementSibling Node / Element
childNodes children NodeList / HTMLCollection

Примеры

firstChild vs firstElementChild

// HTML: <ul>\n  <li>Первый</li>\n</ul>
const ul = document.querySelector('ul');

console.log(ul.firstChild);        // TextNode "\n  " (пробел/перенос!)
console.log(ul.firstElementChild); // <li>Первый</li>

console.log(ul.lastChild);         // TextNode "\n"
console.log(ul.lastElementChild);  // последний <li>

Навигация по соседям

const current = document.querySelector('.active');

// Следующий узел (может быть текстовым)
console.log(current.nextSibling);

// Следующий элемент (пропускает текстовые узлы)
const next = current.nextElementSibling;
const prev = current.previousElementSibling;

if (next) next.classList.add('next');
if (prev) prev.classList.add('prev');

Обход childNodes

const container = document.querySelector('.container');

// childNodes включает текстовые узлы
for (const node of container.childNodes) {
  if (node.nodeType === Node.TEXT_NODE) {
    console.log('Текст:', node.textContent.trim());
  } else if (node.nodeType === Node.ELEMENT_NODE) {
    console.log('Элемент:', node.tagName);
  }
}

Практический обход: карусель

function nextSlide(current) {
  return current.nextElementSibling || current.parentElement.firstElementChild;
}

function prevSlide(current) {
  return current.previousElementSibling || current.parentElement.lastElementChild;
}

Частые ошибки

  • Ожидание Element от firstChild — между тегами часто есть пробелы, которые являются текстовыми узлами; используйте firstElementChild если нужен элемент.
  • Проверка на null — если у элемента нет соседей/детей, свойства возвращают null; без проверки — TypeError.
  • Изменение childNodes в циклеchildNodes — живая коллекция; удаление узлов во время итерации сдвигает индексы; переведите в массив: [...el.childNodes].

Связанные темы

Ресурсы