` или `\n\n
После скрипта
\n\n\n```\n\nПроцесс:\n1. **Парсинг HTML**: Движок браузера парсит HTML и доходит до тега `\n```\n\nВывод будет:\n```\n1. Синхронный код скрипта (часть задачи парсинга)\n2. Микрозадача из промиса\n3. Колбэк setTimeout (новая макротаска)\n```\n\nПочему такой порядок? Потому что выполнение всего тела `
← Назад к вопросам

Является ли скрипт внутри HTML макротаской?

1.2 Junior🔥 241 комментариев
#HTML и CSS

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

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

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

Отличный и очень тонкий вопрос, который касается фундаментальных механизмов событийного цикла (Event Loop) в браузере. Давайте разберемся детально.

Краткий ответ

Нет. Скрипт внутри HTML (<script>... </script> или <script src="...">) не является макротаской (macrotask) в классическом понимании модели событийного цикла. Однако его выполнение инициируется макротаской и является частью задачи (task), которая является более широким понятием, включающим в себя макротаски.

Главная путаница возникает из-за различий в терминологии: в разных источниках "task" и "macrotask" часто используют как синонимы, но технически в спецификациях WHATWG/HTML фигурирует термин "task".

Детальное объяснение

1. Что такое задача (Task / Macrotask)?

В событийном цикле браузера задача (task) — это атомарная единица работы. К задачам относятся:

  • Выполнение JavaScript-кода (включая внешние и inline скрипты).
  • Обработка событий (например, click, keypress).
  • setTimeout и setInterval (их колбэки).
  • Операции, связанные с вводом-выводом (например, загрузка файла).
  • Рендеринг страницы (отрисовка, пересчёт стилей, layout) — хотя это отдельная стадия цикла.

Когда браузер встречает <script>, он планирует задачу на его загрузку (если внешний) и выполнение. Эта задача помещается в очередь задач (Task Queue).

2. Жизненный цикл выполнения <script>

Давайте рассмотрим на примере:

<!DOCTYPE html>
<html>
<head></head>
<body>
  <div>До скрипта</div>

  <script>
    console.log('Скрипт выполняется');
    // Этот код представляет собой синхронную часть задачи
  </script>

  <div>После скрипта</div>
</body>
</html>

Процесс:

  1. Парсинг HTML: Движок браузера парсит HTML и доходит до тега <script>.
  2. Создание задачи: Для выполнения этого скрипта создается задача. Если скрипт внешний (src="..."), то сначала будет подзадача на его загрузку по сети.
  3. Блокировка парсинга: Для обычных (не async/defer) скриптов парсинг и рендеринг HTML приостанавливаются. Это ключевой момент — браузер выделяет целую задачу на выполнение скрипта.
  4. Выполнение кода: Движок JavaScript (например, V8) выполняет код внутри тега <script> синхронно, как часть текущей задачи.
  5. Завершение задачи: После выполнения последней строки скрипта задача завершается. Событийный цикл может перейти к следующей задаче (например, рендерингу) или выполнить микрозадачи.

3. Сравнение с классическими макротасками (setTimeout)

Выполнение inline-скрипта — это первоначальная задача, запланированная парсером. Колбэк setTimeout — это отложенная задача, которая попадает в очередь после истечения таймера.

<script>
  console.log('1. Синхронный код скрипта (часть задачи парсинга)');

  setTimeout(() => {
    console.log('3. Колбэк setTimeout (новая макротаска)');
  }, 0);

  Promise.resolve().then(() => {
    console.log('2. Микрозадача из промиса');
  });
</script>

Вывод будет:

1. Синхронный код скрипта (часть задачи парсинга)
2. Микрозадача из промиса
3. Колбэк setTimeout (новая макротаска)

Почему такой порядок? Потому что выполнение всего тела <script> — это одна исходная задача. Внутри нее создаются микрозадача (промис) и новая макротаска (таймаут).

4. Ключевые выводы и практические следствия

  • Скрипт — это не колбэк макротаски, а сама задача целиком. Макротаски (в терминологии сообщества) часто ассоциируются с функциями обратного вызова (колбэками setTimeout, событий), которые планируются в очередь. Скрипт же выполняется как "корневая" задача.
  • Блокирующая природа. Поскольку выполнение обычного скрипта — это задача, и она блокирует парсинг HTML и рендеринг, это объясняет, почему "тяжелые" скрипты "подвешивают" страницу. Событийный цикл не может перейти к задаче рендеринга, пока не завершится задача выполнения скрипта.
  • Async/Defer изменяют правила. Атрибуты async и defer меняют способ планирования задачи выполнения скрипта, но в итоге его код всё равно выполняется как задача (не как микрозадача).

Заключение

Говоря максимально точно: выполнение JavaScript-кода внутри тега <script> представляет собой выполнение задачи (task) событийного цикла. Эта задача может включать в себя как синхронный код, так и асинхронные операции, которые внутри себя порождают микрозадачи и новые макротаски.

Понимание этого различия критически важно для:

  • Оптимизации загрузки страницы (расстановки async/defer).
  • Объяснения порядка выполнения кода.
  • Понимания, почему, например, Promise.resolve().then(...) выполнится перед setTimeout(..., 0), даже если они вызваны в одном скрипте.

Поэтому на собеседовании правильным будет ответ: "Скрипт выполняется как задача (task) событийного цикла, что часто приравнивают к макротаске, но технически он является первоисточником задачи, а не колбэком, помещённым в очередь макротасок, как setTimeout".

Является ли скрипт внутри HTML макротаской? | PrepBro