Почему работать с DOM напрямую накладно для производительности?

🎯 Зачем спрашивают
  • Проверить знание принципов рендера браузера (reflow, repaint).
  • Понять, знает ли кандидат, почему работа напрямую с DOM = потенциальная боль для перфоманса.
  • Проверить, умеет ли объяснить «на пальцах» (без абстрактного «потому что тормозит»).
 
📝 Ответ
💡
DOM (Document Object Model) — структурированное представление HTML, XML и SVG документов в виде дерева, позволяющее взаимодействовать с ней через JavaScript.
DOM — это внешний по отношению к JS API:
  • Взаимодействие с DOM — это не просто изменение переменной в памяти.
  • Каждый вызов вроде element.innerHTML = ... — это дорогостоящее обращение к API браузера.
Это как постоянно бегать за пределы программы, вместо работы внутри неё.
 
💡
Обращение к внешнему API по дефолту накладная операция, требующая дополнительных ресурсов
 
Изменения DOM вызывают перерисовку (reflow & repaint)
Когда ты меняешь DOM:
  • Браузер должен:
    • Пересчитать layout (reflow),
    • Перерисовать элементы (repaint),
    • Потянуть стили, отступы, размеры,
    • Заново отрендерить часть или весь интерфейс.
    •  
      ⚠️
      Каждое изменение = полная перерисовка
      Есть ошибочное мнение, что любое ручное изменение в DOM приведет к полному перерендеру DOM дерева. Это не так. Даже если вы вручную через JS измените элемент, это не приведет к полной перерисовке страницы.
       
      <div id="a">A</div> <div id="b">B</div> <script> const a = document.getElementById('a'); const b = document.getElementById('b'); const before = b; a.textContent = 'A (изменено)'; // меняем только один узел console.log(b === before); // true → элемент B не пересоздан </script>
       
🔁 Частые изменения DOM = много перерисовок = тормоза.
Пример:
for (let i = 0; i < 1000; i++) { const el = document.createElement('div'); el.textContent = i; document.body.appendChild(el); // <- каждое добавление может триггерить reflow }
Трудно оптимизировать
  • Когда ты работаешь напрямую с DOM — ты сам отвечаешь за оптимизацию.
  • Тебе нужно:
    • Кэшировать элементы,
    • Использовать DocumentFragment
    • Дебаунсить/троттлить обновления,
    • Следить за тем, чтобы ничего лишнего не перерисовывалось.
Иначе браузер будет бесконечно ререндерить интерфейс при каждом изменении.
 
React, Vue, Svelte и другие — решают это, убирая прямую работу с DOM и заменяя её декларативным описанием:
"Вот как должен выглядеть интерфейс — сделай как надо".
 
⚖️ Компромиссы
  • ✅ Работа с DOM напрямую: полный контроль, иногда быстрее для микрооптимизаций.
  • ❌ Работа с DOM напрямую: высокая когнитивная нагрузка, риск багов, сложнее поддерживать.
  • React/Vue: удобнее, но не всегда быстрее → абстракция тоже стоит ресурсов.
 
🔎 Встречные вопросы
  • Когда есть смысл напрямую работать с DOM (без фреймворков и библиотек)?
  • Что такое reflow и repaint, в чём разница?
  • Как можно минимизировать количество reflow?
 
🚩 Красные флаги
  • Потому что изменение в DOM требует полной его перерисовки
 
🛠 Практика
 
📚 Источники / ссылки