В этой главе мы займемся размещением сценариев в HTML-документе, чтобы иметь возможность использовать их для оперативной модификации HTML-документа. Для вставки JavaScript-кoдa в НТМL-страницу обычно используют элемент <script>.
Первая программа
Чтобы ваша первая пpoгpaммa (или сценарий) JavaScript запустилась, ее нужно внедрить в НТМL-документ.
Сценарии внедряются в HTML-документ различными стандартными способами:
- поместить код непосредственно в атрибут события HTML-элемента;
- поместить код между открывающим и закрывающим тегами
<script>; - поместить все ваши скрипты во внешний файл (с расширением .js), а затем связать его с документом HTML.
JavaScript в элементе script
Самый простой способ внедрения JavaScript в HTML-документ – использование тега <script>. Теги <script> часто помещают в элемент <head>, и ранее этот способ считался чуть ли не обязательным. Однако в наши дни теги <script> используются как в элементе <head>, так и в теле веб-страниц.
Таким образом, на одной веб-странице могут располагаться сразу несколько сценариев. В какой последовательности браузер будет выполнять эти сценарии?
Как правило, выполнение сценариев браузерами происходит по мере их загрузки.
Браузер читает HTML-документ сверху вниз и, когда он встречает тег <script>, рассматривает текст программы как сценарий и выполняет его. Остальной контент страницы не загружается и не отображается, пока не будет выполнен весь код в элементе <script>.
Обратите внимание: мы указали атрибут language тега <script>, указывающий язык программирования, на котором написан сценарий. Значение атрибута language по умолчанию – JavaScript, поэтому, если вы используете скрипты на языке JavaScript, то вы можете не указывать атрибут language.
JavaScript в атрибутах событий HTML-элементов
Вышеприведенный сценарий был выполнен при открытии страницы и вывел строку: «Привет, мир!». Однако не всегда нужно, чтобы выполнение сценария начиналось сразу при открытии страницы. Чаще всего требуется, чтобы программа запускалась при определенном событии, например при нажатии какой-то кнопки.
В следующем примере функция JavaScript помещается в раздел <head> HTML-документа. Вот пример HTML-элемента <button> с атрибутом события, обеспечивающим реакцию на щелчки мышью. При нажатии кнопки генерируется событие onclick.
Внешний JavaScript
Если JavaScript-кода много – его выносят в отдельный файл, который, как правило, имеет расширение .js.
Чтобы включить в HTML-документ JavaScript-кoд из внешнего файла, нужно использовать атрибут src (source) тега <script>. Его значением должен быть URL-aдpec файла, в котором содержится JS-код:
<script src="/scripts/script.js"></script>
В этом примере указан абсолютный путь к файлу с именем script.js, содержащему скрипт (из корня сайта). Сам файл должен содержать только JavaScript-кoд, который иначе располагался бы между тегами <script> и </script>.
По аналогии с элементом <img> атрибуту src элемента <script> можно назначить полный URL-aдpec, не относящийся к домену текущей НТМL-страницы:
<script src=" http://www.somesite.com/script.js"></script>
На заметку: Подробнее о путях файлов читайте в разделе «Абсолютные и относительные ссылки».
Чтобы подключить несколько скриптов, используйте несколько тегов:
<script src="/scripts/script1.js"></script>
<script src="/scripts/script2.js"></script>
...
Примечание: Элемент <script> с атрибутом src не может содержать дополнительный JаvаSсriрt-код между тегами <script> и </script>, хотя внешний сценарий выполняется, встроенный код игнорируется.
Независимо от того, как JS-код включается в НТМL-документ, элементы <script> интерпретируются браузером в том порядке, в котором они расположены в HTML-документе. Сначала интерпретируется код первого элемента <script>, затем браузер приступает ко второму элементу <script> и т. д.
Внешние скрипты практичны, когда один и тот же код используется во многих разных веб-страницах. Браузер скачает js-файл один раз и в дальнейшем будет брать его из своего кеша, благодаря чему один и тот же скрипт, содержащий, к примеру, библиотеку функций, может использоваться на разных страницах без полной перезагрузки с сервера. Кроме этого, благодаря внешним скриптам, упрощается сопровождение кода, поскольку вносить изменения или исправлять ошибки приходится только в одном месте.
Примечание: Во внешние файлы копируется только JavaScript-код без указания открывающего и закрывающего тегов <script> и </script>.
Расположение тегов <script>
Вы уже знаете, что браузер читает HTML-документ сверху вниз и, начинает отображать страницу, показывая часть документа до тега <script>. Встретив тег <script>, переключается в JavaScript-режим и выполняет сценарий. Закончив выполнение, возвращается обратно в HTML-режим и отображает оставшуюся часть документа.
Это наглядно демонстрирует следующий пример. Метод alert() выводит на экран модальное окно с сообщением и приостанавливает выполнение скрипта, пока пользователь не нажмёт «ОК»:
Если на странице используется много скриптов JavaScript, то могут возникнуть длительные задержки при загрузке, в течение которых пользователь видит пустое окно браузера. Поэтому считается хорошей практикой все ссылки нa javaScript-cцeнapии указывать после контента страницы перед закрывающим тегом <body>:
<body>
<!-- Контент страницы -->
<script src="scriptl.js"></script>
<script src="script2.js"></script>
</body>
Такое расположение сценариев позволяет браузеру загружать страницу быстрее, так как сначала загрузится контент страницы, а потом будет загружаться код сценария.
Для пользователей это предпочтительнее, потому что страница полностью визуализируется в браузере до обработки JavaScript-кoдa.
Отложенные и асинхронные сценарии
Как отмечалось ранее, по умолчанию файлы JavaScript-кода прерывают синтаксический анализ (парсинг) HTML-документа до тех пор, пока скрипт не будет загружен и выполнен, тем самым увеличивая промежуток времени до первой отрисовки страницы.
Возьмём пример, в котором элемент <script> расположен где-то в середине страницы:
<html>
<body>
какой-то текст...
<script src="script.js"></script>
Этот текст не будет показан, пока браузер не выполнит script.js.
</body>
</html>
В этом примере, пока пока браузер не загрузит и не выполнит script.js, он не покажет часть страницы под ним. Такое поведение браузера называется «синхронным» и может доставить проблемы, если мы загружаем несколько JavaScript-файлов на странице, так как это увеличивает время её отрисовки.
А что, если HTML-документ на самом деле не зависит от этих JS-файлов, а разработчик желает контролировать то, как внешние файлы загружаются и выполняются?
Кардинально решить проблему загрузки скриптов помогут атрибуты async и defer элемента <script>.
Атрибут async
Async используется для того, чтобы указать браузеру, что скрипт может быть выполнен «асинхронно».
При обнаружении тега <script async src="..."> браузер не останавливает обработку HTML-документа для загрузки и выполнения скрипта, выполнение может произойти после того, как скрипт будет получен параллельно с разбором документа. Когда скрипт будет загружен – он выполнится.
Для сценариев с атрибутом async не гарантируется выполнение скриптов в порядке их добавления, например:
<html>
<head>
</head>
<body>
<script async src="script1.js"></script>
<script async src="script2.js"></script>
<!-- контент -->
</body>
</html>
В примере второй скрипт может быть выполнен перед первым, поэтому важно, чтобы между этими сценариями не было зависимостей.
Примечание: Атрибут async используется, если нужно разрешить браузеру продолжить загрузку страницы, не дожидаясь завершения загрузки и выполнения сценария.
Атрибут defer
Атрибут defer откладывает выполнение скрипта до тех пор, пока вся HTML-страница не будет загружена полностью.
Как и при асинхронной загрузке скриптов — JS-файл может быть загружен, в то время как HTML-документ ещё грузится. Однако, даже если скрипт будет полностью загружен ещё до того, как браузер закончит обработку страницы, он не будет выполнен до тех пор, пока HTML-документ не обработается до конца.
<html>
<head>
<script defer src="script1.js"></script>
<script defer src="script2.js"></script>
</head>
<body>
<!-- контент -->
</body>
</html>
Несмотря на то, что в приведенном примере теги <script defer src="..."> включены в элемент <head> HTML-документа, выполнение сценариев не начнется, пока браузер не дойдет до закрывающего тега </html>.
Кроме того, в отличие от async, относительный порядок выполнения скриптов с атрибутом defer будет сохранён.
Применение атрибута defer бывает полезным, когда в коде скрипта предусматривается работа с HTML-документом, и разработчик должен быть уверен, что страница полностью получена.
Примечание: Атрибуты async и defer поддерживаются только для внешних файлов сценариев, т.е. работают только при наличии атрибута src.
Итоги
- JavaScript можно добавить в HTML-документ с помощью элемента
<script>двумя способами:- Определить встроенный сценарий, который располагается непосредственно между парой тегов
<script>и</script>. - Подключить внешний файл с JavaScript-кодом через
<script src="путь"></script>.
- Определить встроенный сценарий, который располагается непосредственно между парой тегов
- Если JavaScript-код используется в нескольких страницах, то его лучше подключать в качестве внешнего сценария. Это существенно облегчает сопровождение и редактирование кода, а также ускорит загрузку и обработку веб-страниц – внешний сценарий загружается браузером всего один раз (в дальнейшем он будет извлекаться из кэша браузера).
- Атрибут
deferсигнализирует браузеру, что загрузку сценария можно начать немедленно, но его выполнение следует отложить до тех пор, пока весь HTML-документ будет загружен. - В тех случаях, когда файл скрипта содержит функции, взаимодействующие с загружаемым HTML-документом или существует зависимость от другого файла на странице необходимо, чтобы HTML-документ был полностью загружен, прежде чем скрипт будет выполнен. Как правило, такая ссылка нa javaScript-cцeнapий помещается в низ страницы перед закрывающим тегом <body>, чтобы убедиться, что для его работы весь документ был разобран. Однако, в ситуации, когда по каким-либо причинам JS-файл должен быть размещён в другом месте документа — атрибут
deferможет быть полезен. - Атрибут
deferсохраняет относительную последовательность выполнения скриптов, аasync– нет. - Скрипт с атрибутом
asyncвыполняется асинхронно с обработкой страницы, когда скрипт будет загружен – он выполнится, даже если HTML-документ ещё не полностью готов. - Для JS-файлов, которые не зависят от других файлов, атрибут
asyncбудет наиболее полезен. Поскольку нам не важно, когда скрипт будет исполнен, асинхронная загрузка — наиболее подходящий вариант.
Задачи
-
Всплывающее окно
Перед вами простой HTML-документ. Разместите в теле НТМL-страницы сценарий, выводящий всплывающее окно с надписью: "Привет, javascript!"
Решение:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Мой первый javascript</title> </head> <body> <p>Это обычный HTML документ</p> <script> alert("Привет, javascript!"); </script> </body> </html>
-
Подключение внешнего скрипта
Включите в НТМL-страницу сценарий из внешнего файла script.js, который расположен в той же директории, где располагается и сам HTML-документ.
Решение:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Мой первый javascript</title> </head> <body> <p>Это обычный HTML документ</p> <script src="script.js"></script> </body> </html>
-
Внешний скрипт с встроенным JаvаSсriрt кодом
Внешний файл script.js содержит сценарий, который выводит модальное окно с надписью: "Сработал внешний скрипт – script.js!". Какая надпись будет выведена в окне браузера?
Показать решение<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <script src="script.js"> alert("Привет, javascript!"); </script> </body> </html>Решение:
Элемент
<script>с атрибутомsrcне может содержать дополнительный JаvаSсriрt-код между тегами<script>и</script>, так как сработает только внешний сценарий, а встроенный код игнорируется. Таким образом будет выведена фраза: "Сработал внешний скрипт – script.js!".
-
Какой скрипт выполнится последним?
В примере ниже к HTML-документу подключен скрипт example.js. Скрипт относительно мал и загружается гораздо обыстрее, чем сам документ. В каком случае сценарий выполнится последним?
Вариант 1.Вариант 2.<head> <script src="example.js"></script> </head>Вариант 3.<head> <script defer src="example.js"></script> </head>Показать решение<head> <script async src="example.js"></script> </head>Решение:
Атрибут
deferоткладывает выполнение скрипта до тех пор, пока вся HTML-страница не будет загружена полностью. Таким образом, во втором случае сценарий будет выполнен последним.


Комментарии
<code>, несколько строчек кода — в теги<pre><code>...ваш код...</code></pre>.