Встроенный JavaScript: варианты и особенности применения

Раздел: Веб-разработка -> Встраивание скриптов на страницу

Основные способы встраивания JavaScript

Рекомендуемый способ: внешний скрипт с атрибутом defer

Скрипт подключается через тег script с атрибутом src и defer. Браузер загружает файл параллельно с парсингом HTML, но выполняет только после полной загрузки документа. Это обеспечивает доступ к DOM и не блокирует отрисовку страницы.

<script src='app.js' defer></script>

Embedded js (встроенный javascript)

Файл app.js:

console.log('DOM готов:', document.querySelector('h1'));

Результат: код выполняется после загрузки HTML, элемент h1 доступен.

Как вставить код непосредственно в разметку без отдельного файла?

Использование тега script без атрибута src. Код выполняется немедленно при парсинге.

<script>alert('Hello');</script>

Цель: быстрые тесты, небольшие скрипты, одностраничные приложения. Проблемы: сложность поддержки, отсутствие кэширования, блокировка разметки.

Ошибка: попытка обратиться к элементу, который ещё не загружен, приводит к null. Решение: разместить скрипт перед закрывающим body или обернуть в DOMContentLoaded.

Как подключить внешний файл скрипта в заголовке head без дополнительных атрибутов?

Тег script с src в head. Скрипт загружается и выполняется синхронно, блокируя парсинг HTML.

<head>...<script src='blocking.js'></script>...</head>

Цель: скрипты, которые должны выполниться до построения DOM (например, полифиллы). Проблемы: задержка загрузки страницы, если файл большой.

Если скрипт не может быть загружен (сетевой сбой), страница может остаться незагруженной. Используйте async или defer для некритичных скриптов.

Как загрузить скрипт асинхронно с помощью атрибута async?

Атрибут async позволяет загружать скрипт параллельно, но выполнение происходит сразу после загрузки, независимо от состояния парсинга HTML.

<script src='analytics.js' async></script>

Цель: скрипты, не зависящие от DOM (счётчики, трекеры). Проблемы: порядок выполнения не гарантируется; если несколько async-скриптов, они выполняются по мере загрузки.

Если скрипт использует document.write, он может нарушить структуру страницы. Для современных скриптов async безопасен.

Как разместить скрипт в конце body, чтобы гарантировать доступ к DOM?

Помещение тега script перед закрывающим тегом body обеспечивает, что все элементы уже распаршены.

<body>...<script src='footer.js'></script></body>

Цель: простой способ без атрибутов, поддержка старых браузеров. Проблемы: скрипт начинает загружаться только после полной загрузки HTML, что может быть медленно при больших файлах.

Если скрипт динамически вставляет контент до закрытия body, это может вызвать перерисовку. Для ускорения используйте defer.

Как выполнить код после полной загрузки DOM с помощью события DOMContentLoaded?

Обёртка кода в слушатель события DOMContentLoaded позволяет выполнить скрипт в любом месте head или body.

<script>document.addEventListener('DOMContentLoaded', function() { console.log('DOM загружен'); });</script>

Цель: гарантированный доступ к DOM при размещении скрипта в head. Проблемы: код не выполнится, если скрипт загружается через async и уже после события.

Не путайте с событием load (ждёт все ресурсы). DOMContentLoaded срабатывает раньше.

Как использовать ES6 модули для организации кода?

Тег script с атрибутом type='module' позволяет использовать import и export. Модули по умолчанию ведут себя как defer.

<script type='module' src='main.js'></script>

В main.js:

import { helper } from './helper.js'; helper();

Цель: современная модульная архитектура, изоляция области видимости. Проблемы: требуется современный браузер; CORS при локальной разработке (file:// не работает).

Ошибка: попытка импортировать без правильного пути или расширения .js. Решение: всегда указывать полный относительный путь.

Как динамически загрузить скрипт из JavaScript по требованию?

Создание элемента script через document.createElement и добавление его в DOM.

const script = document.createElement('script'); script.src = 'widget.js'; document.head.appendChild(script);

Цель: ленивая загрузка, оптимизация загрузки страницы. Проблемы: сложность отслеживания завершения загрузки, возможные конфликты.

Если добавить скрипт в head, он выполнится асинхронно. Для синхронной загрузки используйте async = false.

Расширенные примеры встраивания скриптов

Динамическая загрузка с обработкой успеха и ошибки

Пример
function loadScript(src, callback) {
  const script = document.createElement('script');
  script.src = src;
  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error('Ошибка загрузки ' + src));
  document.head.appendChild(script);
}
loadScript('https://example.com/analytics.js', (err, scr) => {
  if (err) console.error(err);
  else console.log('Скрипт загружен', scr.src);
});
Результат: при успешной загрузке в консоль выводится сообщение; при ошибке выводится объект ошибки.

Динамический импорт ES6 модулей через import()

Пример
async function loadModule() {
  try {
    const module = await import('./lazyModule.js');
    module.default(); // или экспортированная функция
  } catch (e) {
    console.error('Не удалось загрузить модуль', e);
  }
}
document.getElementById('btn').addEventListener('click', loadModule);
Результат: при клике на кнопку загружается модуль и вызывается его функция. В консоли видно момент загрузки.

Загрузка скрипта с проверкой целостности (Subresource Integrity)

Пример
<script src='https://cdn.example.com/lib.js' integrity='sha384-...' crossorigin='anonymous'></script>
Пример
// Динамическое создание с integrity
const script = document.createElement('script');
script.src = 'https://cdn.example.com/lib.js';
script.integrity = 'sha384-...';
script.crossOrigin = 'anonymous';
document.head.appendChild(script);
Результат: браузер проверяет хеш файла; если не совпадает, скрипт не выполняется и генерируется ошибка.

Последовательная загрузка нескольких скриптов с помощью Promise

Пример
function loadScriptPromise(src) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = src;
    script.onload = resolve;
    script.onerror = reject;
    document.head.appendChild(script);
  });
}
async function loadSequence() {
  try {
    await loadScriptPromise('first.js');
    console.log('Первый загружен');
    await loadScriptPromise('second.js');
    console.log('Второй загружен');
  } catch (e) {
    console.error('Ошибка в последовательности', e);
  }
}
loadSequence();
Результат: скрипты загружаются и выполняются строго по порядку. В консоли выводятся сообщения после каждой загрузки.

Использование атрибута nomodule для обратной совместимости

Пример
<script type='module' src='modern.js'></script>
<script nomodule src='legacy.js'></script>
Результат: современные браузеры загружают modern.js (модуль), старые игнорируют type='module' и загружают legacy.js.

Встроенный JavaScript - comments

En
Embedded js (javascript)