ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Category:

JavaScript: порядок выполнения скриптов и модулей на HTML-странице

Запустил у себя на компьютере следующий скрипт из подраздела 1.1 «Браузерное окружение, спецификации» второй части учебника по JavaScript:

Файл myscript.js:
"use strict";

// заменим цвет фона на красный,
document.body.style.background = "red";

// а через секунду вернём как было
setTimeout(() => document.body.style.background = "", 1000);

И неожиданно получил ошибку «Uncaught TypeError: Cannot read property 'style' of null» (при запуске скрипта со страницы учебника ошибки не происходит).

Мне было понятно, что я неправильно написал HTML-страницу, с которой загружаю скрипт, но в первой части учебника проблем с нею не было:
<!doctype html>

<meta charset="utf-8">

<script src="myscript.js"></script>

Как оказалось, из этого мой браузер («Microsoft Edge» на движке «Chromium») конструирует такой код (посмотрел в инструментах разработчика (F12), пункт меню «Elements»):
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="myscript.js"></script>
  </head>
  <body></body>
</html>

И тут я вспомнил, что в подразделе 13.1 «Модули, введение» первой части учебника я читал, что обычные скрипты (как в данном случае у меня) загружаются и запускаются по мере загрузки HTML-страницы.

Получается, что мой скрипт начинает свою работу до появления у HTML-страницы элемента body (как видно выше, скрипт загружается в разделе head HTML-документа, до загрузки body, ведь документ загружается сверху вниз, от начала к концу), поэтому при попытке обращения к этому элементу не может его найти в HTML-документе. Из-за этого выдается ошибка.

(Добавление от 21 мая 2021 г.: сейчас читаю подраздел 1.3 «Навигация по DOM-элементам» второй части учебника и в нем про это тоже рассказано.)

С модулями (это такой же файл-скрипт, только в HTML у тега script должен быть атрибут type="module") такой ошибки не произойдет, потому что хоть модули и загружаются по мере загрузки HTML-страницы, но их запуск происходит после полной загрузки HTML-страницы.

Таким образом, чтобы исправить обсуждаемую ошибку, в данном случае есть минимум три возможных способа:

1. Загрузить файл myscript.js (сам этот файл не меняем) с HTML-страницы как модуль:
<!doctype html>

<meta charset="utf-8">

<script src="myscript.js" type="module"></script>

2. Загрузить файл myscript.js (сам этот файл не меняем) с HTML-страницы с атрибутом defer (на русский это слово переводится как «отложить»; имеется в виду — отложить запуск скрипта до полной загрузки HTML-страницы) в теге script:
<!doctype html>

<meta charset="utf-8">

<script src="myscript.js" defer></script>

3. Переставить загрузку и запуск скрипта myscript.js (сам этот файл не меняем) на HTML-странице после (ниже) открывающего тега body. Например, так:
<!doctype html>

<meta charset="utf-8">

<body></body>

<script src="myscript.js"></script>
Или так:
<!doctype html>

<meta charset="utf-8">

<body>
  <script src="myscript.js"></script>
</body>
Tags: Образование, Программирование, Сайтостроение
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments