Тег <script>

13.05.2017
Смотрите видео
на Youtube

Тег <script> позволяет внедрить код непосредственно на страницу или подключить из внешнего файла.


<script>
  // Inline JavaScript code here
</script>

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

Теги <script> выполняются в том же порядке, в котором они встречаются на странице. Это относится и к встроенным скриптам, и к внешним.


<script>
    var x = 3;
</script>
<script>
    alert(x);
    // Will alert '3';
</script>

Когда встречается тег <script>, браузер останавливает парсинг HTML и начинает загрузку и выполнение скрипта. Это может значительно замедлить отрисовку, если какие-то тяжелые скрипты расположены вверху страницы. Поэтому рекомендуют подключать скрипты перед закрывающим тегом <body>.

Можно представить, что браузер последовательно перемещается от тега к тегу, выполняя все встречающиеся теги <script>. Это означает, что узлы DOM доступны для скрипта (например, через querySelectorAll), только если их открывающий тег располагается выше в документе, чем тег <script>.

В HTML5 появились логические атрибуты async и defer, позволяющие влиять на порядок выполнения скриптов.

Атрибут async говорит браузеру, что скрипт может выполняться асинхронно. Согласно спецификации, async следует использовать только с внешними файлами скриптов. Когда внешний скрипт имеет этот атрибут, файл может быть загружен, в то время как браузер продолжает парсинг HTML. А после загрузки парсинг приостанавливается для выполнения сценария.

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

Атрибут defer позволяет отложить выполнение, пока документ не будет обработан. Подобно async, defer должен использоваться только с внешними файлами скриптов. В отличие от async, код c defer будет выполняться в том порядке, в котором он располагается на странице. Он просто откладывается до тех пор, пока HTML не будет полностью проанализирован. Это аналогично событию DOMContentLoaded или jQuery.ready.

Если одновременно указать и async и defer, сработает только async.

Атрибут type позволяет задать MIME-тип скрипта. В HTML5 его можно не указывать, по умолчанию его значение text/javascript. Но если указать неподдерживаемый тип — скрипт не будет выполняться. По этому принципу работают javascript-шаблонизаторы, позволяющие добавлять на страницу код, который не выполняется, а обрабатывается самим шаблонизатором.

Атрибут integrity является частью спецификации Subresource Integrity (SRI), которая позволяет браузерам проверять, что получаемые ими файлы доставляются без каких-либо изменений. Это актуально при подключении файлов, например, из CDN. Значением атрибута integrity должен быть хэш для содержимого файла.


<script src="https://example.com/script.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"></script>

Первая часть указывает, какой алгоритм хеширования использовался (на текущий момент доступны sha256, sha384 и sha512), а вторая часть — закодированное в base64 значение хеша.

Спецификация Subresource Integrity на текущий момент поддерживается в Firefox, Chrome и Опере.

Еще один атрибут тега <script> — crossorigin. По умолчанию, браузеры не предоставляют доступ к данным об ошибках, если скрипт находится на другом домене. Вместо этого браузеры сообщают о бессмысленной ошибке без дополнительных данных.

Однако вы можете попросить браузеры включить CORS для ваших скриптов. Для этого тегу <script> нужно добавить атрибут crossorigin, а файл должен отдаваться с заголовком Access-Control-Allow-Origin: *. Атрибут crossorigin может иметь одно из двух значений: anonymous, которое означает, что не будут передаваться никакие учетные данные, и use-credentials, которое говорит, что запросы будут передавать учетные данные.

В HTML5 есть еще два атрибута, которые поддерживаются только в IE — for и event. Они позволяют привязать выполнение скрипта к определенному событию, например, window.load.


<script for="window" event="onload">
    alert("Hi!")
</script>

И последний момент. Если тег скрипт динамически добавлен на страницу как DOM элемент, то он выполнится браузером:


var script = document.createElement('script');
script.textContent = 'alert("Test")';
document.head.appendChild(script);

А если с помощью innerHTML — то нет:


document.head.innerHTML += '<script>alert("Test")</script>';