← Назад к вопросам

Как получить доступ к узлу с помощью JS?

2.0 Middle🔥 191 комментариев
#JavaScript Core#Браузер и сетевые технологии

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как получить доступ к узлу с помощью JS?

Доступ к DOM узлам - основополагающий навык в JavaScript. Есть несколько способов получить элемент, каждый с собственными нюансами и производительностью. Разберу все актуальные методы и лучшие практики.

1. document.getElementById

Один из самых быстрых методов - O(1) в большинстве браузеров:

const element = document.getElementById("myId");

if (element) {
  element.textContent = "Updated";
  element.classList.add("active");
}

Ограничение: id должны быть уникальны на странице. Это даже не рекомендация - это требование HTML spec.

2. querySelector и querySelectorAll

Мощный и гибкий способ с селекторами CSS:

// Единственный элемент (первый найденный)
const button = document.querySelector("button.primary");
const input = document.querySelector("input[type='email']");
const nested = document.querySelector(".header > nav");

// Все элементы
const allButtons = document.querySelectorAll("button");
const items = document.querySelectorAll(".list-item");

// Итерация
allButtons.forEach((button) => {
  button.addEventListener("click", () => {
    console.log("Clicked");
  });
});

// Преобразование в массив
const buttonsArray = Array.from(allButtons);
const buttonsSpread = [...allButtons]; // Современный способ

Осторожно: querySelectorAll возвращает статичный NodeList (не live collection).

3. getElementById vs querySelector

Сравнение:

// getElementById - быстрее
const byId = document.getElementById("main"); // O(1)

// querySelector - медленнее, но гибче
const bySelector = document.querySelector("#main"); // O(n)

// Когда селектор сложный, querySelector может быть медленнее
const slowQuery = document.querySelector(
  "div.container > section.content p:last-child"
); // медленнее, чем getElementById

Рекомендация: используйте getElementById для частых обращений к одному элементу.

4. getElementsByClassName и getElementsByTagName

Живые коллекции (live collections) - обновляются при изменении DOM:

// Live collection - обновляется автоматически
const activeItems = document.getElementsByClassName("active");
console.log(activeItems.length); // 5

const newItem = document.createElement("div");
newItem.className = "active";
document.body.appendChild(newItem);

console.log(activeItems.length); // 6 - автоматически обновилось!

// getElementsByTagName - тоже live
const allDivs = document.getElementsByTagName("div");

// querySelectorAll - статичная, не обновляется
const staticDivs = document.querySelectorAll("div");
console.log(staticDivs.length); // останется 10, не 11

Отличие важно для производительности: живые коллекции медленнее при частых обращениях.

5. Доступ к потомкам через элемент

const container = document.getElementById("container");

// Поиск только внутри контейнера
const child = container.querySelector(".child");
const children = container.querySelectorAll(".child");

// Альтернатива
const firstChild = container.querySelector(".item:first-child");
const lastChild = container.querySelector(".item:last-child");

// DOM свойства для навигации
const parent = container.parentElement;
const siblings = container.parentElement?.children;
const nextSibling = container.nextElementSibling;
const prevSibling = container.previousElementSibling;

6. Новый querySelector вариант :scope

const container = document.getElementById("main");

// :scope означает сам контейнер
const direct = container.querySelector(":scope > .child"); // только прямые потомки

// vs без :scope (ищет везде)
const allInTree = container.querySelector(".child"); // может быть глубже

// Пример:
// <div id="main">
//   <div class="child"></div>       <- нашёл
//   <div>
//     <div class="child"></div>     <- не нашёл с :scope >
//   </div>
// </div>

7. Производительность - выбор метода

// БЫСТРО - O(1)
const byId = document.getElementById("id");
const byClass = document.getElementsByClassName("class")[0];

// МЕДЛЕННО - O(n), но часто нужно
const bySelector = document.querySelector(".complex .selector");

// ОЧЕНЬ МЕДЛЕННО - парсит CSS селектор каждый раз
for (let i = 0; i < 1000; i++) {
  document.querySelector(".item"); // Плохо!
}

// Правильно - кэшируем
const items = document.querySelectorAll(".item");
for (let item of items) {
  console.log(item);
}

8. В React - используйте ref

В React прямой доступ к DOM anti-pattern:

// Плохо
function MyComponent() {
  const handleClick = () => {
    const element = document.getElementById("myButton");
    element.textContent = "Clicked!";
  };
  return <button id="myButton">Click me</button>;
}

// Хорошо - через ref
import { useRef } from "react";

function MyComponent() {
  const buttonRef = useRef<HTMLButtonElement>(null);

  const handleClick = () => {
    if (buttonRef.current) {
      buttonRef.current.textContent = "Clicked!";
    }
  };

  return (
    <button ref={buttonRef} onClick={handleClick}>
      Click me
    </button>
  );
}

9. Проверка существования элемента

// querySelector возвращает null если не найден
const element = document.querySelector(".maybe-exists");

if (element) {
  element.textContent = "Found!";
} else {
  console.log("Element not found");
}

// Safe navigation
document.querySelector("#header")?.classList.add("sticky");

// Проверка многих элементов
const buttons = document.querySelectorAll("button");
if (buttons.length > 0) {
  buttons[0].focus();
}

10. closest() - поиск вверх по дереву

const button = document.querySelector("button");

// Найти ближайший контейнер с классом
const container = button.closest(".modal");

if (container) {
  console.log("Button inside modal");
}

// Пример использования - делегирование событий
document.addEventListener("click", (e) => {
  const target = e.target as HTMLElement;
  const itemRow = target.closest(".item-row");

  if (itemRow) {
    console.log("Clicked item:", itemRow.dataset.id);
  }
});

Итоговая рекомендация

// 1. Для уникальных элементов - id
const header = document.getElementById("header");

// 2. Для селекторов - querySelector
const activeTab = document.querySelector(".tabs .active");

// 3. Для коллекций - querySelectorAll
const items = document.querySelectorAll(".item");

// 4. В React - useRef
const inputRef = useRef<HTMLInputElement>(null);

// 5. Для делегирования - closest()
document.addEventListener("click", (e) => {
  const target = e.target as HTMLElement;
  const item = target.closest(".clickable");
});

В современном коде querySelector семейство методов вытеснило getElement* методы благодаря гибкости CSS селекторов. Но getElementById все еще самый быстрый вариант для уникальных элементов.