Что произойдет, если тег скрипта содержит ссылку на внешний файл скрипта

Обновлено: 03.07.2024

Клиентская сторона — это программа, которая может сопровождать HTML-документ или быть встроена непосредственно в него. Программа выполняется на клиентском компьютере при загрузке документа или в другое время, например, при активации ссылки. Поддержка сценариев в HTML не зависит от языка сценариев.

Сценарии предлагают авторам средства для расширения HTML-документов активными и интерактивными способами. Например:

  • Сценарии могут оцениваться при загрузке документа для динамического изменения содержимого документа.
  • Скрипты могут сопровождать форму для обработки ввода по мере его ввода. Дизайнеры могут динамически заполнять части формы на основе значений других полей. Они также могут гарантировать, что входные данные соответствуют заданным диапазонам значений, что поля взаимно согласованы и т. д.
  • Скрипты могут запускаться событиями, влияющими на документ, такими как загрузка, выгрузка, фокус элемента, движение мыши и т. д.
  • Скрипты могут быть связаны с элементами управления формы (например, кнопками) для создания графических элементов пользовательского интерфейса.

Есть два типа сценариев, которые авторы могут прикреплять к HTML-документу:

  • Те, которые выполняются один раз, когда документ загружается агентом пользователя. Скрипты, которые появляются в элементе SCRIPT, выполняются при загрузке документа. Для пользовательских агентов, которые не могут или не будут обрабатывать сценарии, авторы могут включать альтернативный контент с помощью элемента NOSCRIPT.
  • Те, которые выполняются каждый раз, когда происходит определенное событие. Эти сценарии могут быть назначены ряду элементов через встроенные атрибуты событий.

Примечание. Эта спецификация содержит более подробную информацию о сценариях в разделах, посвященных макросам сценариев.

18.2 Разработка документов для пользовательских агентов, поддерживающих сценарии

В следующих разделах обсуждаются вопросы, касающиеся пользовательских агентов, поддерживающих сценарии.

18.2.1 Элемент SCRIPT

Начальный тег: обязателен, Конечный тег: обязателен

src = uri [CT] Этот атрибут указывает расположение внешнего скрипта. type = content-type [CI] Этот атрибут определяет язык сценариев содержимого элемента и переопределяет язык сценариев по умолчанию. Язык сценариев указывается как тип содержимого (например, «текст/javascript»). Авторы должны предоставить значение для этого атрибута. Для этого атрибута нет значения по умолчанию. language = cdata [CI] Устарело. Этот атрибут определяет язык сценариев содержимого этого элемента. Его значение является идентификатором языка, но поскольку эти идентификаторы не являются стандартными, этот атрибут устарел в пользу type . defer [CI] Когда установлено, этот логический атрибут дает агенту пользователя подсказку о том, что сценарий не собирается генерировать какое-либо содержимое документа (например, нет «document.write» в javascript), и, таким образом, агент пользователя может продолжить синтаксический анализ и рендеринг.

Атрибуты, определенные в другом месте

Элемент SCRIPT помещает сценарий в документ. Этот элемент может появляться любое количество раз в HEAD или BODY документа HTML.

Сценарий может быть определен в содержимом элемента SCRIPT или во внешнем файле. Если атрибут src не установлен, пользовательские агенты должны интерпретировать содержимое элемента как сценарий. Если src имеет значение URI, пользовательские агенты должны игнорировать содержимое элемента и получать скрипт через URI. Обратите внимание, что атрибут charset относится к кодировке символов скрипта, обозначенной атрибутом src; это не касается содержимого элемента SCRIPT.

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

Синтаксис данных скрипта зависит от языка скрипта.

18.2.2 Указание языка сценариев

Поскольку HTML не зависит от конкретного языка сценариев, авторы документов должны явно указывать агентам пользователя язык каждого сценария. Это можно сделать либо с помощью объявления по умолчанию, либо с помощью локального объявления.

Язык сценариев по умолчанию

Авторы должны указать язык сценариев по умолчанию для всех сценариев в документе, включив следующее объявление META в HEAD :

где "тип" – это тип контента, обозначающий язык сценариев. Примеры значений включают "text/tcl", "text/javascript", "text/vbscript".

где "тип" снова является типом контента, обозначающим язык сценариев.

Пользовательские агенты должны определить язык сценариев по умолчанию для документа в соответствии со следующими шагами (от самого высокого к самому низкому приоритету):

  1. Если в каких-либо объявлениях META указан «Content-Script-Type», последний в потоке символов определяет язык сценариев по умолчанию.
  2. В противном случае, если какие-либо заголовки HTTP указывают "Content-Script-Type", последний заголовок в потоке символов определяет язык сценариев по умолчанию.

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

Локальное объявление языка сценариев

Атрибут type должен быть указан для каждого экземпляра элемента SCRIPT в документе. Значение атрибута type для элемента SCRIPT переопределяет язык сценариев по умолчанию для этого элемента.

В этом примере мы объявляем язык сценариев по умолчанию как "text/tcl". Включаем в шапку один СКРИПТ, сценарий которого находится во внешнем файле и написан на языке сценариев "text/vbscript". Мы также включаем в тело один СКРИПТ, который содержит собственный скрипт, написанный на "text/javascript".

Ссылки на элементы HTML из сценария

Каждый язык сценариев имеет свои собственные правила обращения к объектам HTML из сценария. Эта спецификация не определяет стандартный механизм обращения к объектам HTML.

Однако скрипты должны ссылаться на элемент в соответствии с присвоенным ему именем. Механизмы сценариев должны соблюдать следующие правила приоритета при идентификации элемента: атрибут имени имеет приоритет над идентификатором, если установлены оба атрибута. В противном случае можно использовать тот или иной вариант.

18.2.3 Внутренние события

onload = script [CT] Событие onload происходит, когда пользовательский агент заканчивает загрузку окна или всех кадров в FRAMESET . Этот атрибут может использоваться с элементами BODY и FRAMESET. onunload = script [CT] Событие onunload происходит, когда пользовательский агент удаляет документ из окна или фрейма. Этот атрибут может использоваться с элементами BODY и FRAMESET. onclick = script [CT] Событие onclick происходит, когда кнопка указывающего устройства нажимается на элемент. Этот атрибут может использоваться с большинством элементов. ondblclick = script [CT] Событие ondblclick возникает, когда кнопка указывающего устройства дважды щелкается по элементу. Этот атрибут может использоваться с большинством элементов. onmousedown = script [CT] Событие onmousedown происходит, когда кнопка указывающего устройства нажимается на элемент. Этот атрибут может использоваться с большинством элементов. onmouseup = script [CT] Событие onmouseup происходит, когда кнопка указывающего устройства отпускается над элементом. Этот атрибут может использоваться с большинством элементов. onmouseover = script [CT] Событие onmouseover происходит, когда указывающее устройство перемещается на элемент. Этот атрибут может использоваться с большинством элементов. onmousemove = script [CT] Событие onmousemove происходит, когда указывающее устройство перемещается, когда оно находится над элементом. Этот атрибут может использоваться с большинством элементов. onmouseout = script [CT] Событие onmouseout возникает, когда указывающее устройство отодвигается от элемента. Этот атрибут может использоваться с большинством элементов. onfocus = script [CT] Событие onfocus происходит, когда элемент получает фокус либо с помощью указывающего устройства, либо с помощью навигации с помощью табуляции. Этот атрибут может использоваться со следующими элементами: A, AREA, LABEL, INPUT, SELECT, TEXTAREA и BUTTON. onblur = script [CT] Событие onblur возникает, когда элемент теряет фокус либо из-за указывающего устройства, либо из-за навигации с помощью табуляции. Его можно использовать с теми же элементами, что и onfocus . onkeypress = script [CT] Событие onkeypress происходит, когда клавиша нажата и отпущена над элементом. Этот атрибут может использоваться с большинством элементов. onkeydown = script [CT] Событие onkeydown происходит, когда клавиша нажимается на элемент. Этот атрибут может использоваться с большинством элементов. onkeyup = script [CT] Событие onkeyup происходит, когда клавиша отпускается над элементом. Этот атрибут может использоваться с большинством элементов. onsubmit = script [CT] Событие onsubmit возникает при отправке формы. Это относится только к элементу FORM. onreset = script [CT] Событие onreset возникает при сбросе формы. Это относится только к элементу FORM. onselect = script [CT] Событие onselect возникает, когда пользователь выбирает текст в текстовом поле. Этот атрибут может использоваться с элементами INPUT и TEXTAREA. onchange = script [CT] Событие onchange происходит, когда элемент управления теряет фокус ввода, и его значение было изменено с момента получения фокуса. Этот атрибут применяется к следующим элементам: INPUT, SELECT и TEXTAREA.

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

Элементы управления, такие как INPUT, SELECT, BUTTON, TEXTAREA и LABEL, реагируют на определенные внутренние события. Если эти элементы не отображаются в форме, их можно использовать для расширения графического пользовательского интерфейса документа.

Например, авторы могут захотеть включить в свои документы кнопки, которые не отправляют форму, но все еще связываются с сервером, когда они активированы.

В следующих примерах показаны некоторые возможные элементы управления и поведение пользовательского интерфейса на основе внутренних событий.

В следующем примере userName является обязательным текстовым полем. Когда пользователь пытается покинуть поле, событие onblur вызывает функцию JavaScript, чтобы подтвердить, что userName имеет допустимое значение.

Вот еще один пример JavaScript:

Вот пример VBScript обработчика событий для текстового поля:

Вот тот же пример с использованием Tcl:

Вот пример JavaScript для привязки событий в скрипте. Во-первых, вот простой обработчик кликов:

Вот более интересный обработчик окна:

В Tcl это выглядит так:

Обратите внимание, что "document.write" или эквивалентные инструкции во встроенных обработчиках событий создают и записывают в новый документ, а не изменяют текущий.

18.2.4 Динамическое изменение документов

Сценарии, которые выполняются при загрузке документа, могут динамически изменять содержимое документа. Возможность сделать это зависит от самого языка сценариев (например, оператор «document.write» в объектной модели HTML, поддерживаемой некоторыми поставщиками).

Динамическое изменение документа можно смоделировать следующим образом:

  1. Все элементы SCRIPT оцениваются в порядке загрузки документа.
  2. Все конструкции сценария в данном элементе SCRIPT, которые генерируют SGML CDATA, оцениваются. Их объединенный сгенерированный текст вставляется в документ вместо элемента SCRIPT.
  3. Сгенерированный CDATA оценивается повторно.

Документы HTML должны соответствовать HTML DTD как до, так и после обработки любых элементов SCRIPT.

В следующем примере показано, как скрипты могут динамически изменять документ. Следующий скрипт:

Имеет тот же эффект, что и эта HTML-разметка:

18.3 Разработка документов для пользовательских агентов, не поддерживающих сценарии

В следующих разделах обсуждается, как авторы могут создавать документы, которые работают для пользовательских агентов, не поддерживающих сценарии.

18.3.1 Элемент NOSCRIPT

Начальный тег: обязателен, Конечный тег: обязателен

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

Пользовательские агенты, которые не поддерживают сценарии на стороне клиента, должны отображать содержимое этого элемента.

В следующем примере пользовательский агент, выполняющий СЦЕНАРИЙ, включит в документ некоторые динамически созданные данные. Если пользовательский агент не поддерживает сценарии, пользователь все равно может получить данные по ссылке.

18.3.2 Скрытие данных сценария от пользовательских агентов

Пользовательские агенты, которые не распознают элемент SCRIPT, скорее всего, отобразят содержимое этого элемента в виде текста. Некоторые обработчики сценариев, в том числе для языков JavaScript, VBScript и Tcl, позволяют заключать операторы сценария в комментарий SGML. Пользовательские агенты, которые не распознают элемент SCRIPT, таким образом, будут игнорировать комментарий, в то время как интеллектуальные механизмы обработки сценариев поймут, что сценарий в комментариях должен быть выполнен.

Еще одно решение проблемы — хранить скрипты во внешних документах и ​​ссылаться на них с помощью атрибута src.

Комментирование скриптов в JavaScript
Подсистема JavaScript позволяет использовать строку " " из синтаксического анализатора JavaScript.

Комментирование скриптов в VBScript
В VBScript символ одинарной кавычки заставляет остальную часть текущей строки рассматриваться как комментарий. Поэтому его можно использовать, чтобы скрыть строку "-->" от VBScript, например:

Как вы, наверное, знаете, тег script используется для указания JavaScript, который должен выполняться на веб-странице. Тег скрипта может либо включать код JavaScript напрямую, либо указывать URL-адрес, с которого должен быть загружен скрипт.

Теги сценария выполняются в том порядке, в котором они появляются

Эта идея должна быть интуитивно понятной, когда вы читаете этот код:

Это менее интуитивно (но не менее верно) при работе с внешними ресурсами.

Аналогичным образом это работает для комбинаций локальных и удаленных скриптов.

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

Элементы на странице не будут отображаться до тех пор, пока все предшествующие им теги сценария не будут загружены и выполнены. Это означает, что вы можете делать всевозможные сумасшедшие вещи, когда вы настраиваете страницу перед ее загрузкой, если вы готовы принять удар по производительности.

Однако это не применяется, если вы добавляете теги script в DOM после того, как страница начала загружаться с помощью document.appendChild или подобного. Эти теги будут загружаться всякий раз, когда браузер сочтет нужным, и в произвольном порядке.

При выполнении тега скрипта доступно все, что выше его в DOM (но не все, что ниже).

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

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

асинхронно и отложенно

В HTML5 добавлено несколько инструментов для управления выполнением скриптов.

  • async означает «выполнять это всякий раз». Более конкретно это означает: мне все равно, если вы выполните это после загрузки всей страницы и выполнения всех остальных скриптов. Это очень полезно для кодов отслеживания аналитики, например, когда никакой другой код на странице не зависит от их выполнения. Определение переменной или функции в асинхронном коде, который нужен странице, — плохая новость, поскольку вы не можете знать, когда асинхронный код действительно запустится.
  • defer означает «подождать, пока анализатор завершит выполнение этого». Это примерно эквивалентно привязке вашего скрипта к событию DOMContentLoaded или использованию jQuery.ready. Когда код запустится, все в DOM будет доступно для использования. В отличие от async , код defer будет выполняться в том порядке, в котором он появляется в HTML-коде страницы, он просто откладывается до тех пор, пока HTML-код не будет полностью проанализирован.

Атрибут типа

Исторически (начиная с Netscape 2) не имело большого значения, указывали ли вы type="text/javascript" в своих тегах script или просто оставляли это поле пустым. Если вы установите какой-либо тип MIME, который не является вариантом JavaScript, в качестве типа, браузер не будет его выполнять. Это может быть здорово, если вы хотите определить свой собственный язык:

Тогда фактическое выполнение этого кода зависит от вас, т.е.:

Определение функции runEmeraldCode остается читателю в качестве упражнения.

Если у вас есть извращенное желание, вы также можете переопределить тип по умолчанию для каждого тега скрипта на странице с помощью метатега:

Или заголовок Content-Script-Type.

Подробнее о допустимых типах см. в Краткой истории необычных языков сценариев в Интернете.

Есть атрибут целостности?

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

Я еще не видел его в дикой природе, но если вы знаете сайт, использующий его, оставьте комментарий ниже.

перекрестное происхождение тоже важно!

Это делается для того, чтобы вы, например, не могли отправлять запросы на веб-сайты ваших конкурентов, которые удаляют любые учетные записи, которые могут быть у текущего пользователя (нехорошо!). Однако его связь с тегами script несколько случайна. Идея заключается в том, что если вы применяете обработчик к событию window.onerror, этот обработчик получает некоторую информацию о странице и скрипте, которой вам, возможно, не следует иметь, если вы загружаете код с внешнего сайта. В защищенных браузерах эта информация не включается, если вы не укажете crossorigin .

однако crossorigin не является каким-то волшебным средством защиты, он указывает браузеру пройти обычную проверку доступа CORS, отправив запрос OPTIONS и проверив заголовки Access-Control.

document.currentScript

Он не поддерживает IE, что делает его чем-то вроде новинки, но есть свойство document.currentScript, указывающее на текущий выполняемый скрипт. Это может быть очень полезно, если вы хотите извлечь атрибуты из тега script, который используется для встраивания. Лично я очень рад, что он не полностью поддерживается, поскольку это усложнило бы часть работы, которую мы выполняем в Eager, по установке кодов для встраивания.

onafterscriptexecute ?!

Это совершенно бесполезно, поскольку поддерживается только в Firefox. Это, вместе с onbeforescriptexecute, позволяет вам привязать событие, которое будет выполняться до и после запуска каждого скрипта на странице, что довольно круто.

Если вам интересно, объекты события содержат ссылку на выполняемый скрипт, а событие before может отменить выполнение, вызвав preventDefault() .

для / события

По сей день спецификация HTML5 включает редко встречающийся ранее специфичный для IE метод привязки кода к событию.Предполагается, что вы сможете сделать это, чтобы тег script не запускался до события загрузки страницы:

На самом деле я не могу заставить это работать в Chrome или Firefox (что делает их несовместимыми со стандартами), но есть большая вероятность, что это все еще работает в IE.

ПОДПИСЬ

Как и вашим родителям, трудно поверить, что когда-то JavaScript был молодым. Однако был день, когда вы не могли быть уверены, будет ли данный браузер поддерживать JavaScript или нет. Хуже того, вы не могли быть уверены, что браузер даже знает, что такое тег скрипта. И если браузер не распознает тег, он должен отображать его как общий встроенный элемент, а это означает, что все ваши секретные JavaScript-коды будут отображаться на странице в виде текста!

К счастью, спецификация оказалась достаточно полезной, чтобы предоставить решение, обернув ваш код во что-то, что неподдерживающий браузер интерпретировал бы как HTML-комментарий:

Конечно, как и многое другое, XHTML все усугубил. XML имеет особый метод экранирования содержимого, которое может содержать закрывающие теги и тому подобное, так родился CDATA:

При этом ваш код будет действительным XHTML. Это не повлияет на его функциональность, но будет невероятно важно для вашей самооценки как веб-разработчика.

В браузерах также есть полезный метод, позволяющий сообщить людям, у которых не включен JavaScript, чтобы они ушли, — тег noscript.

Если вы наблюдательны, то поймете, что noscript не принимает аргумент типа, что делает его взаимодействие со страницами, использующими несколько типов скриптов, несколько двусмысленным. Фактическое поведение варьировалось от браузера к браузеру, но включало отображение блоков noscript, если какой-либо тег скрипта, использованный ранее в документе, имел неподдерживаемый тип . Это означает, что вполне возможно, что ранние noscript не появлялись, а те, что ниже на странице, отображались.

Теги сценария и innerHTML

Теги скрипта, которые динамически добавляются на страницу через модель DOM, выполняются браузером:

Теги скрипта, которые динамически добавляются на страницу через innerHTML, не являются:

Почему это происходит, непонятно, но это забавный ответ на банальный вопрос: «Возможно ли, чтобы в инспекторе Chrome отображался тег скрипта, который на самом деле не запускался?» Что, в свою очередь, делает его отличным способом разыграть коллег.

Читайте также: