HTML-тег <script>
HTML-тег <script> встраивает или подключает JavaScript на страницу. Изучите src, async vs defer, type="module", размещение и атрибуты с примерами.
HTML-тег <script> объявляет клиентский скрипт — почти всегда JavaScript — в HTML-документе. Скрипты добавляют интерактивность: валидацию форм, динамическое обновление содержимого, работу с изображениями и реакцию на события пользователя. Тег может содержать скрипт встроенно (между открывающим и закрывающим тегами) или загружать внешний файл через атрибут src. Для более широкого обзора добавления скриптов на страницу см. HTML scripts.
Если вы подключаете внешний файл со скриптами, не встраивайте скрипт в тот же тег <script>.
HTML-тег <script> можно размещать в элементе <head>, а также внутри элемента <body>. Скрипты, которые должны выполняться первыми, часто помещают в элемент <head> с атрибутом defer или в конце элемента <body>. Тег <script> можно использовать в HTML-документе несколько раз.

Синтаксис
Тег <script> всегда идёт парами — открывающий <script> и закрывающий </script>. Встроенный код размещается между ними; для внешнего файла оставьте тег пустым и укажите в src путь к файлу:
<script>
// inline JavaScript here
console.log("Hello from inline script");
</script>
<script src="app.js"></script>Пример встроенного скрипта
Для выбора HTML-элемента JavaScript обычно использует метод document.getElementById():
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<p id="example"></p>
<script>
document.getElementById("example").innerHTML = "My first JavaScript code";
</script>
</body>
</html>Загрузка внешнего скрипта
В реальных проектах JavaScript почти всегда хранится в отдельном файле .js и загружается с помощью src. Это сохраняет HTML чистым, позволяет браузеру кешировать скрипт и использовать один файл на нескольких страницах:
<script src="app.js" defer></script>Несколько важных замечаний:
- Не смешивайте оба способа. Если присутствует
src, любой код между тегами игнорируется. Используйте либо встроенный код, либоsrc, но не оба в одном теге. type="text/javascript"не нужен. JavaScript является языком сценариев по умолчанию в современном HTML, поэтомуtypeможно полностью опустить. Указывайтеtypeтолько тогда, когда действительно нуженtype="module"(см. ниже).charsetне влияет на внешние скрипты сегодня. Кодировка символов берётся из HTTP-заголовкаContent-Typeфайла (и из кодировки самой страницы), поэтому атрибутcharsetу тега<script>устарел — не полагайтесь на него.
async vs. defer
По умолчанию, когда браузер встречает <script src="..."> при разборе HTML, он останавливает разбор, загружает скрипт, выполняет его и только затем продолжает. Это блокирует отрисовку. boolean-атрибуты async и defer решают эту проблему — оба загружают скрипт параллельно без блокировки разбора — но отличаются тем, когда скрипт выполняется:
| Атрибут | Блокирует разбор? | Когда выполняется | Порядок |
|---|---|---|---|
| (нет) | Да | Немедленно при встрече | В порядке документа |
defer | Нет | После полного разбора HTML, непосредственно перед DOMContentLoaded | В порядке документа |
async | Нет | Как только завершается загрузка | Кто первый загрузится (без порядка) |
<!-- Runs after the page is parsed, in order. Safe for code that touches the DOM. -->
<script src="app.js" defer></script>
<!-- Runs as soon as it loads, order not guaranteed. Good for independent scripts
like analytics that don't depend on other scripts or the parsed DOM. -->
<script src="analytics.js" async></script>Используйте defer, когда скрипты зависят от DOM или друг от друга (наиболее распространённый случай). Используйте async для независимых скриптов, не зависящих от порядка выполнения, например счётчиков аналитики.
async и defer — это boolean-атрибуты: их простое наличие активирует их. Пишите их без значения (defer), а не в старом стиле XHTML defer="defer". То же относится к другим boolean-атрибутам, таким как disabled и checked. Оба атрибута игнорируются во встроенных скриптах (тех, у которых нет src).
Размещение скрипта: <head> или конец <body>
Место расположения <script> имеет значение, поскольку обычный скрипт блокирует разбор:
<head>сdefer— современная рекомендация. Загрузка начинается рано, пока HTML ещё разбирается, а выполнение ожидает готовности DOM. Вы получаете быструю загрузку без блокировки.- Конец
<body>— классический подход. К тому моменту, когда парсер доходит до скрипта, весь DOM уже существует, поэтому скрипт может безопасно обращаться к элементам. Никакие атрибуты не нужны.
<head>
<script src="app.js" defer></script>
</head>
<body>
<!-- page content -->
</body>Избегайте обычного <script src> (без async/defer) в <head>, так как это блокирует отрисовку страницы до тех пор, пока скрипт не будет загружен и выполнен.
ES-модули с type="module"
Установка type="module" превращает скрипт в ES-модуль. Модульные скрипты отличаются от классических:
- Они поддерживают
import/export, что позволяет разделять код по файлам. - Они отложены по умолчанию — модульные скрипты всегда ждут завершения разбора HTML (атрибут
deferне нужен). - Они всегда выполняются в строгом режиме и имеют собственную область видимости верхнего уровня (переменные не утекают в глобальный объект).
<script type="module" src="main.js"></script>
<script type="module">
import { greet } from "./greet.js";
greet("World");
</script>Для поддержки очень старых браузеров, не понимающих модули, можно дополнить модуль запасным скриптом с nomodule — современные браузеры выполняют модуль и игнорируют запасной, старые — наоборот.
Замечание об XHTML и устаревшей разметке
В современном HTML атрибут type не нужен, и содержимое встроенного скрипта не нужно оборачивать в секцию CDATA. Обёртка //<![CDATA[ ... //]]> была нужна только в XHTML, где содержимое скрипта разбиралось как разметка и специальные символы вроде < и & нужно было экранировать или защищать. Если вы пишете стандартный HTML, это можно игнорировать.
Атрибуты
| Атрибут | Значение | Описание |
|---|---|---|
src | URL | URL внешнего файла скрипта (относительный или абсолютный). |
async | (boolean) | Внешний скрипт загружается параллельно и выполняется сразу после загрузки, не блокируя разбор. |
defer | (boolean) | Внешний скрипт загружается параллельно и выполняется по порядку после разбора HTML. |
type | тип медиа | Обычно опускается (JavaScript используется по умолчанию). Установите module для загрузки ES-модуля. |
charset | кодировка | Устарел — не имеет эффекта; кодировка берётся из HTTP-заголовка Content-Type файла. |
crossorigin | anonymous | use-credentials | Настраивает CORS для запроса внешнего скрипта. |
integrity | хеш | Хеш Subresource Integrity для проверки загруженного скрипта. |
Тег <script> поддерживает глобальные атрибуты и атрибуты событий.