Ваши сценарии выполняются синхронно
Ваш код, если сложить это:
1. create script element
2. set its attribute src
3. set its attribute deferred
4. display done...
эта первая часть останавливает выполнение и передает его следующему сценарию
5. script executes and displays Hi
Все очень синхронно ... В Javascript некоторый код выполняется полностью, пока не выполнится до последней строки или не передаст выполнение внутренним системам (таким как XHR или таймер).
Когда кто-то хочет подготовить некоторые части для последующего выполнения, они готовят его с помощью setTimeout
. Даже если тайм-аут короче, чем остальная часть кода, это займет время, которое он выполнит. После завершения выполнения кода. Пример:
// some code
setTimeout(function(){ alert("I'm second alert"); }, 1);
longExecutionTask();
alert("I'm the first alert");
В приведенном выше коде, даже если setTimeout
настроен на выполнение после 1 мс, он не запустится до тех пор, пока код не завершит выполнение, которое заканчивается отображением поля alert
. То же самое происходит в вашем случае. Первая партия кода должна завершиться, прежде чем что-либо еще может запуститься.
Почему вы получаете исключение (в примере 2)
Вы добавили еще немного кода после того, как я написал свой ответ, так что здесь идет дополнительная информация.
Добавление тега скрипта не приведет к его немедленному исполнению. Загрузка скрипта + выполнение произойдет, когда парсер HTML попадет к добавленному элементу SCRIPT
. Он загрузит его в этот момент и оценит / выполнит его содержимое.
- HTML-анализатор начинает анализ вашего документа
HEAD
анализируется, а дочерний тег SCRIPT
анализируется и выполняется. Это выполнение добавляет еще один элемент к тегу BODY
, который еще не проанализирован.
- Parser переходит к
BODY
и анализирует его содержимое (недавно добавленный тег SCRIPT
), который затем загружает скрипт и выполняет его содержимое.
SCRIPT
элементы выполняются немедленно, только когда вы добавлены после того, как ваша страница была проанализирована и уже отображена в браузере. В вашем случае это не так. Первый скрипт выполняется немедленно, а динамически добавляемый выполняется, когда в него попадает парс.