Внешние скрипты, порядок исполнения
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/script-async-defer.
Если JavaScript-кода много – его выносят в отдельный файл, который подключается в HTML:
Здесь /path/to/script.js – это абсолютный путь к файлу, содержащему скрипт (из корня сайта).
Браузер сам скачает скрипт и выполнит.
Можно указать и полный URL, например:
Вы также можете использовать путь относительно текущей страницы. Например, src=»https://learn.javascript.ru/lodash.js» обозначает файл из текущей директории.
Чтобы подключить несколько скриптов, используйте несколько тегов:
На заметку:
Как правило, в HTML пишут только самые простые скрипты, а сложные выносят в отдельный файл.
Браузер скачает его только первый раз и в дальнейшем, при правильной настройке сервера, будет брать из своего кеша.
Благодаря этому один и тот же большой скрипт, содержащий, к примеру, библиотеку функций, может использоваться на разных страницах без полной перезагрузки с сервера.
Если указан атрибут src , то содержимое тега игнорируется.
В одном теге SCRIPT нельзя одновременно подключить внешний скрипт и указать код.
Вот так не сработает:
Нужно выбрать: либо SCRIPT идёт с src , либо содержит код. Тег выше следует разбить на два: один – с src , другой – с кодом, вот так:
Асинхронные скрипты: defer/async
Браузер загружает и отображает HTML постепенно. Особенно это заметно при медленном интернет-соединении: браузер не ждёт, пока страница загрузится целиком, а показывает ту часть, которую успел загрузить.
Если браузер видит тег , то он по стандарту обязан сначала выполнить его, а потом показать оставшуюся часть страницы.
Например, в примере ниже – пока все кролики не будут посчитаны – нижний
не будет показан:
Начинаем считать:
Кролики посчитаны!
Такое поведение называют «синхронным». Как правило, оно вполне нормально, но есть важное следствие.
Если скрипт – внешний, то пока браузер не выполнит его, он не покажет часть страницы под ним.
То есть, в таком документе, пока не загрузится и не выполнится big.js , содержимое будет скрыто:
Этот текст не будет показан, пока браузер не выполнит big.js.
И здесь вопрос – действительно ли мы этого хотим? То есть, действительно ли оставшуюся часть страницы нельзя показывать до загрузки скрипта?
Есть ситуации, когда мы не только НЕ хотим такой задержки, но она даже опасна.
Например, если мы подключаем внешний скрипт, который показывает рекламу или вставляет счётчик посещений, а затем идёт наша страница. Конечно, неправильно, что пока счётчик или реклама не подгрузятся – оставшаяся часть страницы не показывается. Счётчик посещений не должен никак задерживать отображение страницы сайта. Реклама тоже не должна тормозить сайт и нарушать его функциональность.
А что, если сервер, с которого загружается внешний скрипт, перегружен? Посетитель в этом случае может ждать очень долго!
Вот пример, с подобным скриптом (стоит искусственная задержка загрузки):
Важная информация не покажется, пока не загрузится скрипт.
. Важная информация!
Можно поставить все подобные скрипты в конец страницы – это уменьшит проблему, но не избавит от неё полностью, если скриптов несколько. Допустим, в конце страницы 3 скрипта, и первый из них тормозит – получается, другие два его будут ждать – тоже нехорошо.
Кроме того, браузер дойдёт до скриптов, расположенных в конце страницы, они начнут грузиться только тогда, когда вся страница загрузится. А это не всегда правильно. Например, счётчик посещений наиболее точно сработает, если загрузить его пораньше.
Поэтому «расположить скрипты внизу» – не лучший выход.
Кардинально решить эту проблему помогут атрибуты async или defer :
Поддерживается всеми браузерами, кроме IE9-. Скрипт выполняется полностью асинхронно. То есть, при обнаружении браузер не останавливает обработку страницы, а спокойно работает дальше. Когда скрипт будет загружен – он выполнится.
Поддерживается всеми браузерами, включая самые старые IE. Скрипт также выполняется асинхронно, не заставляет ждать страницу, но есть два отличия от async .
Первое – браузер гарантирует, что относительный порядок скриптов с defer будет сохранён.
То есть, в таком коде (с async ) первым сработает тот скрипт, который раньше загрузится:
А в таком коде (с defer ) первым сработает всегда 1.js , а скрипт 2.js , даже если загрузился раньше, будет его ждать.
Поэтому атрибут defer используют в тех случаях, когда второй скрипт 2.js зависит от первого 1.js , к примеру – использует что-то, описанное первым скриптом.
Второе отличие – скрипт с defer сработает, когда весь HTML-документ будет обработан браузером.
Например, если документ достаточно большой…
Много много много букв
…То скрипт async.js выполнится, как только загрузится – возможно, до того, как весь документ готов. А defer.js подождёт готовности всего документа.
Это бывает удобно, когда мы в скрипте хотим работать с документом, и должны быть уверены, что он полностью получен.
async вместе с defer
При одновременном указании async и defer в современных браузерах будет использован только async , в IE9- – только defer (не понимает async ).
Атрибуты async/defer – только для внешних скриптов
Атрибуты async/defer работают только в том случае, если назначены на внешние скрипты, т.е. имеющие src .
При попытке назначить их на обычные скрипты , они будут проигнорированы.
Тот же пример с async :
Важная информация теперь не ждёт, пока загрузится скрипт.
. Важная информация!
При запуске вы увидите, что вся страница отобразилась тут же, а alert из внешнего скрипта появится позже, когда загрузится скрипт.
Эти атрибуты давно «в ходу»
Большинство современных систем рекламы и счётчиков знают про эти атрибуты и используют их.
Перед вставкой внешнего тега понимающий программист всегда проверит, есть ли у него подобный атрибут. Иначе медленный скрипт может задержать загрузку страницы.
Забегая вперёд
Для продвинутого читателя, который знает, что теги можно добавлять на страницу в любой момент при помощи самого javascript, заметим, что скрипты, добавленные таким образом, ведут себя так же, как async . То есть, выполняются как только загрузятся, без сохранения относительного порядка.
Если же нужно сохранить порядок выполнения, то есть добавить несколько скриптов, которые выполнятся строго один за другим, то используется свойство script.async = false .
Выглядит это примерно так:
function addScript(src) < var script = document.createElement('script'); script.src = src; script.async = false; // чтобы гарантировать порядок document.head.appendChild(script); >addScript('1.js'); // загружаться эти скрипты начнут сразу addScript('2.js'); // выполнятся, как только загрузятся addScript('3.js'); // но, гарантированно, в порядке 1 -> 2 -> 3
Более подробно работу со страницей мы разберём во второй части учебника.
Итого
- Скрипты вставляются на страницу как текст в теге , либо как внешний файл через
- Специальные атрибуты async и defer используются для того, чтобы пока грузится внешний скрипт – браузер показал остальную (следующую за ним) часть страницы. Без них этого не происходит.
- Разница между async и defer : атрибут defer сохраняет относительную последовательность скриптов, а async – нет. Кроме того, defer всегда ждёт, пока весь HTML-документ будет готов, а async – нет.
Очень важно не только читать учебник, но делать что-то самостоятельно.
Решите задачки, чтобы удостовериться, что вы всё правильно поняли.
Задачи
Какой скрипт выполнится первым?
важность: 4
В примере ниже подключены два скрипта small.js и big.js .
Если предположить, что small.js загружается гораздо быстрее, чем big.js – какой выполнится первым?
Работа с файлами
Веб-сайт состоит из множества файлов: текстового контента, кода, стилей, медиа-контента, и так далее. Когда вы создаёте веб-сайт, вы должны собрать эти файлы в рациональную структуру на вашем локальном компьютере, убедитесь, что они могут общаться друг с другом, и весь ваш контент выглядит правильно, прежде чем вы, в конечном итоге загрузите их на сервер. В статье Работа с файлами обсуждаются некоторые вопросы, о которых вам следует знать, чтобы вы могли рационально настроить файловую структуру для своего веб-сайта.
Где ваш веб-сайт должен располагаться на вашем компьютере?
Когда вы работаете на веб-сайте локально на вашем компьютере, вы должны держать все связанные файлы в одной папке, которая отражает файловую структуру опубликованного веб-сайта на сервере. Эта папка может располагаться где угодно, но вы должны положить её туда, где вы сможете легко её найти, может быть, на ваш рабочий стол, в домашнюю папку или в корень вашего жёсткого диска.
- Выберите место для хранения проектов веб-сайта. Здесь, создайте новую папку с именем web-projects (или аналогичной). Это то место, где будут располагаться все ваши проекты сайтов.
- Внутри этой первой папки, создайте другую папку для хранения вашего первого веб-сайта. Назовите её test-site (или как-то более творчески).
Небольшое отступление о регистре и пробелах
Вы заметите, что в этой статье, мы просим вас называть папки и файлы полностью в нижнем регистре без пробелов. Это потому что:
- Многие компьютеры, в частности веб-серверы, чувствительны к регистру. Так, например, если вы положили изображение на свой веб-сайт в test-site/MyImage.jpg , а затем в другом файле вы пытаетесь вызвать изображение как test-site/myimage.jpg , это может не сработать.
- Браузеры, веб-серверы и языки программирования не обрабатывают пробелы последовательно. Например, если вы используете пробелы в имени файла, некоторые системы могут отнестись к имени файла как к двум именам файлов. Некоторые серверы заменяют пробелы в вашем имени файла на «%20» (символьный код для пробелов в URI), в результате чего все ваши ссылки будут сломаны. Лучше разделять слова дефисами, чем нижними подчёркиваниями: my-file.html лучше чем my_file.html .
Говоря простым языком, вы должны использовать дефис для имён файлов. Поисковая система Google рассматривает дефис как разделитель слов, но не относится к подчёркиванию таким образом. По этим причинам, лучше всего приобрести привычку писать названия ваших папок и файлов в нижнем регистре без пробелов, разделяя слова дефисами, по крайней мере, пока вы не поймёте, что вы делаете. Так в будущем вы столкнётесь с меньшим количеством проблем.
Какую структуру должен иметь ваш веб-сайт?
Далее, давайте взглянем на то, какую структуру должен иметь наш тестовый сайт. Наиболее распространённые вещи, присутствующие в любом проекте сайта, которые мы создаём: индексный файл HTML и папки, содержащие изображения, файлы стилей и файлы скриптов. Давайте создадим их сейчас:
- index.html : Этот файл обычно содержит контент домашней страницы, то есть текст и изображения, которые люди видят, когда они впервые попадают на ваш сайт. Используя ваш текстовый редактор, создайте новый файл с именем index.html и сохраните его прямо внутри вашей папки test-site .
- Папка images : Эта папка будет содержать все изображения, которые вы используете на вашем сайте. Создайте папку с именем images внутри вашей папки test-site .
- Папка styles : Эта папка будет содержать CSS код, используемый для стилизации вашего контента (например, настройка текста и цвета фона). Создайте папку с именем styles внутри вашей папки test-site .
- Папка scripts : Эта папка будет содержать весь JavaScript-код, используемый для добавления интерактивных функций на вашем сайте (например, кнопки которые загружают данные при клике). Создайте папку с именем scripts внутри вашей папки test-site .
Примечание: На компьютерах под управлением Windows у вас могут возникнуть проблемы с отображением имён файлов, поскольку у Windows есть опция Скрывать расширения для известных типов файлов, включённая по умолчанию. Обычно вы можете отключить её, перейдя в проводник, выбрать вариант Свойства папки. и снять флажок Скрывать расширения для зарегистрированных типов файлов, затем щёлкнуть OK. Для получения более точной информации, охватывающей вашу версию Windows, вы можете произвести поиск в Интернете.
Файловые пути
Для того, чтобы файлы общались друг с другом, вы должны указать файлам путь друг к другу — обычно один файл знает, где находится другой. Чтобы продемонстрировать это, мы вставим немного HTML в наш файл index.html и научим его отображать изображение, которое вы выбрали в статье «Каким должен быть ваш веб-сайт?»
- Скопируйте изображение, которое вы выбрали ранее, в папку images .
- Откройте ваш файл index.html и вставьте следующий код в файл именно в таком виде. Не беспокойтесь о том, что все это значит — позже в этом руководстве мы рассмотрим структуры более подробно.
doctype html> html> head> meta charset="utf-8" /> title>Моя тестовая страницаtitle> head> body> img src="" alt="Моё тестовое изображение" /> body> html>

Некоторые общие правила о путях к файлам:
- Для ссылки на целевой файл в той же директории, что и вызывающий HTML файл, просто используйте имя файла, например, my-image.jpg .
- Для ссылки на файл в поддиректории, напишите имя директории в начале пути, плюс косую черту (forwardslash, слеш), например: subdirectory/my-image.jpg .
- Для ссылки на целевой файл в директории выше вызывающего HTML файла, напишите две точки. Например, если index.html находится внутри подпапки test-site , а my-image.png — внутри test-site , вы можете обратиться к my-image.png из index.html , используя ../my-image.png .
- Вы можете комбинировать их так, как вам нравится, например ../subdirectory/another-subdirectory/my-image.png .
На данный момент это все, что вам нужно знать
Примечание: Файловая система Windows стремится использовать обратный слеш (backslash), а не косую черту (forwardslash), например C:\windows . Это не имеет значения, даже если вы разрабатываете веб-сайт на Windows, вы всё равно должны использовать обычные слеши в вашем коде.
Что должно быть сделано?
К настоящему моменту структура вашей папки должна выглядеть примерно так:

В этом модуле
- Установка базового программного обеспечения
- Каким должен быть ваш веб-сайт?
- Работа с файлами
- Основы HTML
- Основы CSS
- Основы JavaScript
- Публикация вашего веб-сайта
- Как работает Веб
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 3 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
JS — JavaScript File
Файлы JS представляют собой текстовые файлы, которые используются для обслуживания кода на языке программирования JavaScript. Если программисту необходимо выполнение определенной операции на какой-либо веб-странице, он размещает код такой функции, написанный на языке JavaScript, в файле JS. Файлы JS обладают огромным потенциалом и могут выполнять большое кол-во сложнейших операций. Однако это также означает, что файлы JS подвергаются атаке вирусов. Файл JS легко может быть инфицирован вирусами, что требует дополнительных мер по проверке тех файлов, которые получены от незнакомых или малознакомых лиц. Перед внесением таких файлов в память компьютера все файлы JS необходимо проверять на наличие вирусов.
Файл JS в сущности представляет собой текстовый файл. В случае использования файлов такого типа на веб-сайте его обычно помещают в папку с веб-сайтом туда, где хранятся остальные файлы (на сервере веб-сайта). Код HTML, который формирует веб-страницу, содержит также код, который запускает файл JS. При таком вызове файла JS происходит выполнение кода внутри файла JS. Одними из самых популярных действий, которые могут быть указаны в файле JS, являются закрытие и открытие окон, формирование раскрывающихся меню, «захват» информации, заполнение полей форм, а также включение переключающихся изображений.
Вот небольшой, но неполный список программ, которые могут открывать документы JS:
- Adobe Dreamweaver CC (Windows, Mac)
- Adobe ColdFusion Builder 3 (Windows, Mac)
- Microsoft Visual Studio 2013 (Windows)
- Jetbrains IntelliJ IDEA (Windows)
- Es-Computing EditPlus (Windows)
- Apple Dashcode (Mac)
- Bare Bones BBEdit 10 (Mac)
- MacroMates TextMate (Mac)
- Other text editors
- Other web browsers
Работа с файлами в JavaScript
Мнение о том, что JavaScript не умеет взаимодействовать с файловой системой, является не совсем верным. Скорее, речь идет о том, что это взаимодействие существенно ограничено по сравнению с серверными языками программирования, такими как Node.js или PHP. Тем не менее, JavaScript умеет как получать (принимать), так и создавать некоторые типы файлов и успешно обрабатывать их нативными средствами.
В этой статье мы создадим три небольших проекта:
- Реализуем получение и обработку изображений, аудио, видео и текста в формате txt и pdf
- Создадим генератор JSON-файлов
- Напишем две программы: одна будет формировать вопросы (в формате JSON), а другая использовать их для создания теста
Получаем и обрабатываем файлы
Для начала создадим директорию, в которой будут храниться наши проекты. Назовем ее «Work-With-Files-in-JavaScript» или как Вам будет угодно.
В этой директории создадим папку для первого проекта. Назовем ее «File-Reader».
Создаем в ней файл «index.html» следующего содержания:
Здесь мы имеем контейнер-файлоприемник и инпут с типом «file» (для получения файла; мы будем работать с одиночными файлами; для получения нескольких файлов инпуту следует добавить атрибут «multiple»), который будет спрятан под контейнером.
Стили можно подключить отдельным файлом или в теге «style» внутри head:
body < margin: 0 auto; display: flex; justify-content: center; align-items: center; min-height: 100vh; max-width: 768px; background: radial-gradient(circle, skyblue, steelblue); color: #222; >div < width: 150px; height: 150px; display: flex; justify-content: center; align-items: center; font-size: 10em; font-weight: bold; border: 6px solid; border-radius: 8px; user-select: none; cursor: pointer; >input < display: none; >img, audio, video
Можете сделать дизайн по своему вкусу.
Не забываем подключить скрипт либо в head с атрибутом «defer» (нам нужно дождаться отрисовки (рендеринга) DOM; можно, конечно, сделать это в скрипте через обработку события «load» или «DOMContentLoaded» объекта «window», но defer намного короче), либо перед закрывающим тегом «body» (тогда не нужен ни атрибут, ни обработчик). Лично я предпочитаю первый вариант.
Откроем index.html в браузере:

Прежде чем переходить к написанию скрипта, следует подготовить файлы для приложения: нам потребуется изображение, аудио, видео, текст в формате txt, pdf и любом другом, например, doc. Можете использовать мою коллекцию или собрать свою.
Нам часто придется обращаться к объектам «document» и «document.body», а также несколько раз выводить результаты в консоль, поэтому предлагаю обернуть наш код в такое IIFE (это не обязательно):
;((D, B, log = arg => console.log(arg)) => < // наш код // это позволит обращаться к document и document.body как к D и B, соответственно // log = arg =>console.log(arg) - здесь мы используем параметры по умолчанию // это позволит вызывать console.log как log >)(document, document.body)
Первым делом объявляем переменные для файлоприемника, инпута и файла (последний не инициализируем, поскольку его значение зависит от способа передачи — через клик по инпуту или бросание (drop) в файлоприемник):
const dropZone = D.querySelector('div') const input = D.querySelector('input') let file
Отключаем обработку событий «dragover» и «drop» браузером:
D.addEventListener('dragover', ev => ev.preventDefault()) D.addEventListener('drop', ev => ev.preventDefault())
Для того, чтобы понять, зачем мы это сделали, попробуйте перенести изображение или другой файл в браузер и посмотрите, что произойдет. А происходит автоматическая обработка файлов, т.е. то, что мы собираемся реализовать самостоятельно в познавательных целях.
Обрабатываем бросание файла в файлоприемник:
dropZone.addEventListener('drop', ev => < // отключаем поведение по умолчанию ev.preventDefault() // смотрим на то, что получаем log(ev.dataTransfer) // получаем следующее (в случае передачи изображения) /* DataTransfer dropEffect: "none" effectAllowed: "all" => files: FileList length: 0 __proto__: FileList items: DataTransferItemList types: [] __proto__: DataTransfer */ // интересующий нас объект (File) хранится в свойстве "files" объекта "DataTransfer" // извлекаем его file = ev.dataTransfer.files[0] // проверяем log(file) /* File lastModified: 1593246425244 lastModifiedDate: Sat Jun 27 2020 13:27:05 GMT+0500 (Екатеринбург, стандартное время) <> name: "image.png" size: 208474 type: "image/png" webkitRelativePath: "" __proto__: File */ // передаем файл в функцию для дальнейшей обработки handleFile(file) >)
Мы только что реализовали простейший механизм «dran’n’drop».
Обрабатываем клик по файлоприемнику (делегируем клик инпуту):
dropZone.addEventListener('click', () => < // кликаем по скрытому инпуту input.click() // обрабатываем изменение инпута input.addEventListener('change', () => < // смотрим на то, что получаем log(input.files) // получаем следующее (в случае передачи изображения) /* FileList => 0: File lastModified: 1593246425244 lastModifiedDate: Sat Jun 27 2020 13:27:05 GMT+0500 (Екатеринбург, стандартное время) <> name: "image.png" size: 208474 type: "image/png" webkitRelativePath: "" __proto__: File length: 1 __proto__: FileList */ // извлекаем File file = input.files[0] // проверяем log(file) // передаем файл в функцию для дальнейшей обработки handleFile(file) >) >)
Приступаем к обработке файла:
const handleFile = file => < // дальнейшие рассуждения >
Удаляем файлоприемник и инпут:
dropZone.remove() input.remove()
Способ обработки файла зависит от его типа:
log(file.type) // в случае изображения // image/png
Мы не будем работать с html, css и js-файлами, поэтому запрещаем их обработку:
if (file.type === 'text/html' || file.type === 'text/css' || file.type === 'text/javascript') return;
Мы также не будем работать с MS-файлами (имеющими MIME-тип «application/msword», «application/vnd.ms-excel» и т.д.), поскольку их невозможно обработать нативными средствами. Все способы обработки таких файлов, предлагаемые на StackOverflow и других ресурсах, сводятся либо к конвертации в другие форматы с помощью различных библиотек, либо к использованию viewer’ов от Google и Microsoft, которые не хотят работать с файловой системой и localhost. Вместе с тем, тип pdf-файлов также начинается с «application», поэтому такие файлы мы будем обрабатывать отдельно:
if (file.type === 'application/pdf')
Для остальных файлов получаем их «групповой» тип:
// нас интересует то, что находится до слеша const type = file.type.replace(/\/.+/, '') // проверяем log(type) // в случае изображения // image
Посредством switch..case определяем конкретную функцию обработки файла:
switch (type) < // если изображение case 'image': createImage(file) break; // если аудио case 'audio': createAudio(file) break; // если видео case 'video': createVideo(file) break; // если текст case 'text': createText(file) break; // иначе, выводим сообщение о неизвестном формате файла, // и через две секунды перезагружаем страницу default: B.innerHTML = `Unknown File Format!
` const timer = setTimeout(() => < location.reload() clearTimeout(timer) >, 2000) break; >
Функция обработки изображения:
const createImage = image => < // создаем элемент "img" const imageEl = D.createElement('img') // привязываем его к полученному изображению imageEl.src = URL.createObjectURL(image) // проверяем log(imageEl) // помещаем в документ B.append(imageEl) // удаляем ссылку на файл URL.revokeObjectURL(image) >
Функция обработки аудио:
const createAudio = audio => < // создаем элемент "audio" const audioEl = D.createElement('audio') // добавляем панель управления audioEl.setAttribute('controls', '') // привязываем элемент к полученному файлу audioEl.src = URL.createObjectURL(audio) // проверяем log(audioEl) // помещаем в документ B.append(audioEl) // запускаем воспроизведение audioEl.play() // удаляем ссылку на файл URL.revokeObjectURL(audio) >
Функция обработки видео:
const createVideo = video => < // создаем элемент "video" const videoEl = D.createElement('video') // добавляем панель управления videoEl.setAttribute('controls', '') // зацикливаем воспроизведение videoEl.setAttribute('loop', 'true') // привязываем элемент к полученному файлу videoEl.src = URL.createObjectURL(video) // проверяем log(videoEl) // помещаем в документ B.append(videoEl) // запускаем воспроизведение videoEl.play() // удаляем ссылку на файл URL.revokeObjectURL(video) >
Функция обработки текста:
const createText = text => < // создаем экземпляр объекта "FileReader" const reader = new FileReader() // читаем файл как текст // вторым аргументом является кодировка // по умолчанию - utf-8, // но она не понимает кириллицу reader.readAsText(text, 'windows-1251') // дожидаемся завершения чтения файла // и помещаем результат в документ reader.onload = () =>B.innerHTML = `$ ` >
Last, but not least, функция обработки pdf-файлов:
const createIframe = pdf => < // создаем элемент "iframe" const iframe = D.createElement('iframe') // привязываем его к полученному файлу iframe.src = URL.createObjectURL(pdf) // увеличиваем размеры фрейма до ширины и высоты области просмотра iframe.width = innerWidth iframe.height = innerHeight // проверяем log(iframe) // помещаем в документ B.append(iframe) // удаляем ссылку на файл URL.revokeObjectURL(pdf) >
Создаем JSON-файл
Для второго проекта создадим папку «Create-JSON» в корневой директории (Work-With-Files-in-JavaScript).
Создаем файл «index.html» следующего содержания:
Create JSON
Create JSON
