Базові поняття DOM
1. Що таке DOM?
Відповідь:
DOM (Document Object Model) — це об’єктне представлення HTML-документа, яке браузер створює після того, як завантажує HTML-код. DOM дозволяє JavaScript отримувати доступ до вмісту, структури та стилів сторінки та змінювати їх динамічно.
- DOM перетворює HTML у дерево вузлів (nodes).
- Кожен HTML елемент стає об’єктом, з властивостями та методами.
- DOM є частиною Web API, а не частиною самого JavaScript.
🔍 При завантаженні сторінки браузер виконує такі операції:
1. Парсинг HTML
- Коли браузер отримує HTML-документ від сервера, він починає обробляти його пострічково.
- HTML аналізується і поступово перетворюється у DOM-дерево. Кожен тег, атрибут і текст стає відповідним вузлом у цьому дереві.
2. Побудова DOM-дерева
- DOM-дерево формується на основі структури HTML. Це дозволяє JavaScript та іншим скриптам взаємодіяти з елементами сторінки.
- Вузли створюються відповідно до елементів HTML, починаючи з <!DOCTYPE>і кореневого тегу<html>.
3. Виявлення інших ресурсів
- Під час парсингу HTML браузер виявляє посилання на зовнішні ресурси (CSS, JavaScript, зображення).
- Ці ресурси завантажуються паралельно, але їх обробка може впливати на DOM.
4. Блокування при виконанні JavaScript
- Якщо браузер зустрічає JavaScript, він може зупинити парсинг HTML до тих пір, поки скрипт не буде виконаний (якщо він не є async або defer).
- JavaScript може змінювати DOM на льоту: додавати, видаляти або змінювати вузли.
5. Зв’язок з CSSOM
- Після побудови DOM-дерева, браузер інтегрує його з CSS Object Model (CSSOM), створюючи рендер-дерево.
- Це дозволяє розуміти, як стилі застосовуються до елементів DOM.
6. Рендеринг (Rendering)
- На основі DOM і CSSOM браузер визначає, що і як повинно відображатися на екрані.
- DOM-дерево оновлюється в реальному часі, якщо скрипти або дії користувача змінюють структуру HTML.
7. Маніпуляція DOM JavaScript
- JavaScript може використовувати DOM API для:
- Додавання нових елементів (наприклад, через createElementіappendChild).
- Зміни існуючих елементів (наприклад, через textContentабоclassList).
- Обробки подій DOM (наприклад, кліки, наведення тощо).
 
- Додавання нових елементів (наприклад, через 
8. Оновлення та перерисовка
- Зміни в DOM, викликані JavaScript або CSS, призводять до перерисовки (repaint) або перерахунку макета (reflow). Це впливає на продуктивність.
Таким чином, основне завдання браузера при завантаженні сторінки — створити DOM-дерево, яке стане основою для відображення сторінки та її подальшої взаємодії з JavaScript. Якщо потрібні приклади роботи з DOM, дайте знати! 😊
2. Яка структура DOM?
DOM — це ієрархічне дерево вузлів, де:
- Кожен HTML елемент — це вузол-елемент (Element Node).
- Текст всередині елементів і пробіли — це текстовий вузол (Text Node).
- Коментарі — це comment node.
- document— це кореневий об’єкт (root), який представляє всю сторінку.
🔽 Наприклад, HTML:
htmlКопіюватиРедагувати<body>
  <h1>Hello</h1>
</body>
🧠 DOM структура виглядатиме так:
document
 └── html
     └── body
         └── h1
             └── Text node: "Hello"
3. Чим відрізняється document, window, document.documentElement, document.body?
Відповідь:
document.body — це <body> тег — основний вміст сторінки.
window — глобальний об’єкт браузера. Він містить все: document, console, setTimeout і т.д.
document — властивість window, яка представляє поточний HTML документ.
document.documentElement — це <html> тег. Найвищий вузол елементу DOM.
5. Які є типи вузлів (nodes) у DOM?
У DOM існує кілька типів вузлів, найважливіші з них:
- Element nodes – HTML-елементи (<div>,<span>,<input>і т.д.)
- Text nodes – текст усередині елементів ("Привіт"всередині<p>)
- Comment nodes – коментарі <!-- коментар -->
- Document node – сам документ (document)
- DocumentFragment node – фрагмент документу, корисний для оптимізації вставки кількох елементів
Можна перевірити тип вузла:
element.nodeType === 1 // Element
text.nodeType === 3    // Text
comment.nodeType === 8 // Comment
//Це дозволяє відфільтровувати непотрібні вузли під час обходу DOM.6. Які методи використовуються для доступу до елементів в DOM?
Відповідь:
document.getElementById('id') // Повертає один елемент
document.getElementsByClassName('class') // HTMLCollection
document.getElementsByTagName('div') // HTMLCollection
document.querySelector('селектор') // Перший збіг
document.querySelectorAll('селектор') // NodeListdocument.getElementsByName('селектор') // NodeList
Важливо:
HTMLCollection і NodeList схожі, але NodeList може бути статичним (не оновлюється після змін), а HTMLCollection — живий.
getElementById — найшвидший, бо шукає лише по ID.
querySelector/querySelectorAll — найгнучкіші, бо дозволяють використовувати CSS-селектори.
7. Що таке document у JavaScript?
document — це глобальний об’єкт, який представляє DOM поточного HTML-документа. Він надає API для доступу до вузлів, елементів, атрибутів, створення та маніпуляції ними.
Основні методи:
document.getElementById(id)
document.querySelector(selector)
document.createElement(tagName)
📌 Важливо: об’єкт document існує тільки у контексті браузера. У Node.js його немає без бібліотек типу JSDOM.
8. У чому різниця між getElementById, getElementsByClassName, querySelector і querySelectorAll?
Це всі методи для пошуку елементів у DOM:
| Метод | Повертає | Пошук за | Живий? | 
|---|---|---|---|
| getElementById(id) | Один елемент | id | ❌ | 
| getElementsByClassName(class) | HTMLCollection | class | ✅ | 
| getElementsByTagName(tag) | HTMLCollection | tag | ✅ | 
| querySelector(selector) | Один елемент | CSS селектор | ❌ | 
| querySelectorAll(selector) | NodeList | CSS селектор | ❌ | 
document.querySelector(“.card”); // Перший елемент з класом card document.querySelectorAll(“.card”); // Всі з класом card
HTMLCollection — живий список (все ще оновлюється, якщо DOM змінюється). NodeList — неживий, якщо не поданий з childNodes
9. У чому різниця між innerText, textContent та innerHTML?
Відповідь:
| Властивість | Що робить | Включає теги? | Виконує скрипти? | 
|---|---|---|---|
| textContent | Вся текстова інформація | ❌ | ❌ | 
| innerText | Те, що бачить користувач (враховує CSS) | ❌ | ❌ | 
| innerHTML | HTML-вміст | ✅ | ❌ | 
⚠️ Небезпека XSS при використанні innerHTML з несанітайзованими даними.
10. Яка різниця між властивістю (property) і атрибутом (attribute) у DOM?
Атрибут — це значення, яке задається у HTML (<input value="123">), а властивість — це значення, яке зберігається в об’єкті DOM-елемента (input.value).
🔁 Вони синхронізуються тільки при створенні елемента, але потім змінюються незалежно. Напртклад:
<input id="test" value="hello">
const input = document.getElementById("test");
input.value = "world"; // змінилось value, але атрибут у HTML все ще "hello"
input.getAttribute("value"); // "hello"
input.setAttribute("value", "test"); // змінює саме атрибут
11. У чому різниця між event.target і event.currentTarget?
Відповідь:
Ці два властивості дуже важливі при роботі з подіями:
event.currentTarget — елемент, на якому спрацював обробник
event.target — елемент, на якому сталася подія
<div id="parent">
  <button id="child">Натисни мене</button>
</div>
document.getElementById("parent").addEventListener("click", function (event) {
  console.log("target:", event.target);
  console.log("currentTarget:", event.currentTarget);
});
✅ Якщо натиснути кнопку, event.target буде #child, а event.currentTarget — #parent, бо саме на #parent ми повісили слухача.
12. Що таке Event Propagation? Які в нього фази?
Event Propagation — це процес проходження події через DOM, що має три фази:
Bubbling phase (знизу вгору): подія “вспливає” назад до window
Capturing phase (зверху вниз): подія йде від window до цільового елемента
Target phase: подія доходить до елемента, на якому вона відбулась
element.addEventListener("click", handler, useCapture);useCapture = false (за замовчуванням) → обробник спрацює під час bubbling
useCapture = true → обробник спрацює під час capturing
13. Як працює Event Bubbling (вспливання подій)? І навіщо воно потрібно?
Event Bubbling — це коли подія після цільового елемента “вспливає” вгору по DOM дереву, і кожен предок теж отримує шанс її обробити.
<div id="outer">
  <button id="inner">Click me</button>
</div>
outer.addEventListener("click", () => console.log("outer"));
inner.addEventListener("click", () => console.log("inner"));
✅ Клік на кнопку → спочатку виведеться "inner", потім "outer" — це приклад вспливання.
Навіщо це?
- Для делегування подій (дивись нижче)
- Для глобального відстеження
- Можна зупинити вспливання, якщо не хочемо, щоб подія доходила до батьків: event.stopPropagation();
14. Що таке Event Delegation і як його правильно реалізувати?
Event Delegation — це техніка, коли ми додаємо один обробник подій на спільного предка кількох елементів, а не на кожен елемент окремо.
🔧 Наприклад, у списку з 1000 кнопок замість того, щоб додавати 1000 слухачів, ми додаємо один:
<ul id="list">
  <li>Елемент 1</li>
  <li>Елемент 2</li>
  ...
</ul>
document.getElementById("list").addEventListener("click", function (event) {
  if (event.target.tagName === "LI") {
    alert(`Натиснули на: ${event.target.textContent}`);
  }
});
📌 Тут event.target — це li, а слухач висить на ul.
Переваги delegation:
- Менше слухачів → менше пам’яті
- Можна обробляти динамічно створені елементи
- Краще для продуктивності при великій кількості елементів
15. Що таке once: true і навіщо це використовують у addEventListener?
Це опція, яку можна передати при додаванні слухача, і вона означає, що обробник спрацює один раз, після чого автоматично видалиться:
button.addEventListener("click", () => {
  alert("Цей алерт з’явиться тільки один раз");
}, { once: true });
📌 Це дуже зручно для:
- Початкових ініціалізацій
- Кроків в онбордингу
- Одноразових реакцій на дії користувача
16. Як повісити обробник одразу на кілька елементів?
За допомогою forEach або for:
document.querySelectorAll(".btn").forEach(btn =>
  btn.addEventListener("click", handler)
);
❗ Але якщо таких елементів багато і вони динамічно додаються — краще використовувати Event Delegation (як вище).
17. Що таке DOM? Як він пов’язаний з HTML і CSS?
DOM (Document Object Model) — це програмний інтерфейс для HTML і XML документів, який представляє структуру документа у вигляді дерева об’єктів. Кожен елемент HTML (наприклад, <div>, <p>, <span>) стає вузлом (node) у цьому дереві. DOM дозволяє JavaScript динамічно змінювати вміст, структуру та стилі документа.
DOM також включає події, які дозволяють реагувати на дії користувача (натискання миші, введення тексту тощо).
DOM пов’язаний з HTML через парсинг: браузер перетворює HTML-код у DOM-дерево.
CSS використовує DOM для застосування стилів до елементів через селектори.
18. Як додавати, видаляти та змінювати елементи в DOM?
Для маніпуляцій з DOM використовуються такі методи:
classList.add() / classList.remove() — додає або видаляє класи.
Додавання елементів:
createElement(tagName) — створює новий елемент.
appendChild(node) / append(node) — додає елемент в кінець дочірніх.
insertBefore(newNode, referenceNode) — вставляє елемент перед вказаним.
Видалення елементів:
removeChild(node) — видаляє дочірній елемент.
remove() — видаляє елемент з DOM.
Зміна елементів:
innerHTML / textContent — змінює вміст елемента.
setAttribute(name, value) — додає або змінює атрибут.
19. Як працює рендеринг DOM? Які методи оптимізації ви знаєте?
Рендеринг DOM — це процес відображення HTML, CSS і JavaScript на екрані. Він включає кілька етапів:
- Парсинг HTML і побудова DOM-дерева.
- Парсинг CSS і побудова CSSOM (CSS Object Model).
- Об’єднання DOM і CSSOM у Render Tree.
- Layout (розміщення елементів на сторінці).
- Paint (відображення пікселів на екрані).
Оптимізація:
- Використовуйте DocumentFragmentдля додавання великої кількості елементів.
- Уникайте “layout thrashing” (часті зміни геометрії елементів).
- Використовуйте requestAnimationFrameдля анімацій.
- Мінімізуйте кількість рефлоу (reflow) і репейнт (repaint).
Приклад:
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  fragment.appendChild(div);
}
document.body.appendChild(fragment);20. При завантаженні сторінки браузер що робить, покроково
При завантаженні веб-сторінки браузер виконує складний багатокроковий процес. Ось детальний покроковий опис того, що відбувається:
1. Введення URL
- Користувач вводить URL у адресному рядку браузера або натискає на посилання.
2. DNS-запит
- Браузер звертається до DNS-сервера для визначення IP-адреси, пов’язаної з введеним доменним ім’ям (наприклад, example.com).
3. Встановлення TCP-з’єднання
- Браузер використовує протокол TCP/IP для встановлення з’єднання з сервером.
- Якщо сайт використовує HTTPS, браузер також проходить процес TLS/SSL-шифрування для безпечного з’єднання.
4. Відправлення HTTP-запиту
- Браузер відправляє HTTP-запит на сервер, який включає метод запиту (GET, POST тощо) і запитуваний ресурс (наприклад, HTML-файл).
5. Отримання відповіді від сервера
- Сервер відповідає HTTP-відповіддю, яка містить статусний код (наприклад, 200 OK) і запитаний контент (HTML-документ).
6. Парсинг HTML
- Браузер починає обробляти HTML-документ по черзі.
- При зустрічі посилань на інші ресурси (CSS, JS, зображення) браузер виконує додаткові запити для їх завантаження.
7. Побудова DOM-дерева
- HTML-документ перетворюється у Document Object Model (DOM) — дерево вузлів.
8. Парсинг CSS і побудова CSSOM
- CSS-файли та стилі обробляються для створення CSS Object Model (CSSOM), яка визначає стилі всіх елементів.
9. Побудова Render Tree
- DOM і CSSOM об’єднуються для створення Render Tree, яка описує, які елементи сторінки мають бути відображені і як вони виглядають.
10. Візуалізація (Layout і Painting)
- Вираховуються позиції та розміри елементів (Layout).
- Елементи “малюються” (Painting) на екран відповідно до стилів та позицій.
11. Виконання JavaScript
- JavaScript файли виконуються. Це може впливати на DOM і змінювати контент сторінки в реальному часі.
12. Рендеринг і оптимізація
- Після виконання всіх кроків браузер продовжує оптимізувати відображення сторінки, наприклад, за допомогою технік Lazy Loading.
13. Кешування
- Браузер зберігає статичний контент (зображення, CSS, JS) в кеш для швидшого повторного завантаження сторінки.
Цей процес працює у фоновому режимі і зазвичай відбувається дуже швидко, забезпечуючи користувачеві плавний досвід. Якщо є потреба розглянути якийсь із кроків більш детально, дайте знати — я поясню! 🚀
Обхід DOM (DOM Traversal)
Це частина, яка часто забувається на співбесідах, але дуже цінується на senior рівні — вміння ефективно знаходити елементи в DOM без querySelectorAll, з використанням “відносних” властивостей.
21. Яка різниця між childNodes і children?
| Властивість | Що повертає | Тип колекції | 
|---|---|---|
| children | тільки елементи (елемент вузли) | HTMLCollection | 
| childNodes | усі вузли (елементи, текст, коментарі…) | NodeList | 
<div id="test">
  Привіт
  <span>Світ</span>
</div>
const el = document.getElementById("test");
console.log(el.childNodes); // [#text, <span>]
console.log(el.children);   // [<span>]
⚠️ В реальному проєкті childNodes часто містить пробіли або \n — бо браузер бачить і їх як текст.
22. Що таке closest() і чим воно відрізняється від parentElement?
closest(selector) — шукає найближчого предка (включно із самим елементом), який відповідає CSS-селектору.
📌 Відмінність від parentElement:
- parentElementпросто повертає одного батька
- closest()може піднятися вгору хоч до- html, поки не знайде селектор
23. Як перевірити, чи один елемент містить інший у DOM?
Є кілька способів:
node.contains(otherNode) — повертає true, якщо node є предком otherNode.
if (parent.contains(child)) {
  console.log("child inside parent");
}
compareDocumentPosition() — метод, що повертає бітову маску для порівняння позицій двох вузлів:
if (parent.compareDocumentPosition(child) & Node.DOCUMENT_POSITION_CONTAINED_BY) {
  console.log("child всередині parent");
}
Цей метод дає набагато більше гнучкості, але в 90% випадків достатньо contains().
25. Як пройтись по всіх нащадках вузла рекурсивно?
Використовуємо рекурсію:
function walk(node) {
  console.log(node.nodeName);
  node = node.firstChild;
  while (node) {
    walk(node);
    node = node.nextSibling;
  }
}
walk(document.body);
🧠 Це базовий шаблон для обходу DOM-дерева, корисний у складних UI-фреймворках або в тестуванні.
26. Як дізнатись глибину вкладеності елемента в DOM?
Можна підніматись вгору по дереву через parentNode або parentElement і рахувати кроки, поки не дійдемо до document:
function getDomDepth(el) {
  let depth = 0;
  while (el.parentElement) {
    depth++;
    el = el.parentElement;
  }
  return depth;
}
const element = document.querySelector(".some-class");
console.log(getDomDepth(element)); // Наприклад: 4
🔍 Це може бути корисно для:
- створення динамічних індексів елементів
- аналітики DOM-структури
- побудови outline-структури документа
27. Як перевірити, чи два елементи знаходяться в одному дереві (тобто чи мають спільного предка)?
Найпростіший варіант — використовувати compareDocumentPosition():
const relation = node1.compareDocumentPosition(node2);
const areInSameTree = !(relation & Node.DOCUMENT_POSITION_DISCONNECTED);
Або вручну, перевіряючи contains() в обидва боки:
if (node1.contains(node2) || node2.contains(node1)) {
  console.log("В одному дереві");
}
📌 compareDocumentPosition() також може вказати, чи node2 раніше або пізніше node1 в порядку документу, що корисно для сортування.
28. Як працює метод element.matches(selector) і де він застосовується?
matches(selector) — перевіряє, чи елемент відповідає CSS-селектору. Повертає true або false.
const el = document.querySelector("li");
if (el.matches(".active.highlighted")) {
  // якщо елемент має обидва класи — виконається
}
Найчастіше використовується разом із Event Delegation, щоб перевірити, чи саме event.target відповідає певному селектору.
list.addEventListener("click", (e) => {
  if (e.target.matches("li.item")) {
    e.target.classList.toggle("selected");
  }
});
✅ Також корисно при створенні власних UI-компонентів або при фільтрації елементів.
29. Якими способами можна обійти DOM? Які є навігаційні властивості?
DOM Traversal — це процес переміщення по вузлах DOM (вгору, вниз, вбік) для доступу до потрібного елементу.
Найважливіші навігаційні властивості:
🔼 Вгору (до батьків):
- parentNode– найближчий батько (може бути елемент або document)
- parentElement– те саме, але тільки якщо батько є елементом (тобто не- #document)
🔽 До дітей:
- children– HTMLCollection дочірніх елементів (без текстових вузлів)
- childNodes– NodeList всіх дочірніх вузлів (включаючи текст, коментарі)
- firstElementChild/- lastElementChild– перший / останній елемент-дитина
- firstChild/- lastChild– перший / останній будь-який вузол
↔️ До сусідів:
previousSibling / nextSibling – будь-які сусідні вузли
previousElementSibling / nextElementSibling – сусідні елементи
const el = document.querySelector('.item');
const parent = el.parentElement;
const firstChild = el.firstElementChild;
const next = el.nextElementSibling;