Я читал, что defer
не обязательно задержать загрузку внешнего сценария, но он будет отложить выполнение сценария до после того, как HTML был проанализирован.
В качестве эксперимента я добавляю строку в конец файла, содержащего jQuery, который испускает событие, когда выполнение доходит до конца JavaScript:
window.dispatchEvent(new Event('jQuery-executed'));
Я включаю файл jQuery на моей тестовой странице с атрибутом defer
:
<script src="jquery-3.2.1.js" defer onload="console.log('jQuery loaded', Date.now());"></script>
<script>
window.addEventListener('DOMContentLoaded', function(){
console.log('DOMREADY', Date.now());
});
window.addEventListener('jQuery-executed', function(){
console.log('jQuery executed', Date.now());
});
</script>
У меня есть обработчик onload
в теге скрипта, чтобы сообщить мне, когда файл был загружен, а другие функции выводят консольные журналы в DOMContentLoaded и когда выполняется jQuery.
Почему, когда я просматриваю эту страницу, я получаю это?
Неужели все должно происходить в другом порядке? Не следует ли jQuery выполнять только после того, как загруженный файл загружен? И почему это выполняется перед DOMContentLoaded?
Спецификация HTML5 является странной и трудно читаемой, но она говорит, что отложенный контент сценария должен быть оценен до того, как будет запущено событие "load". Если вы думаете об этом, это действительно хорошо: если у вас есть код, ожидающий загрузки скрипта, возможно, потому, что вы хотите использовать какой-то код, предоставленный сценарием. Если событие "load" было запущено до запуска скрипта, было бы бесполезно иметь обработчик "load".
То же самое касается "DOMContentReady": код, ожидающий, что это событие будет правильно срабатывать, ожидает, что все содержимое скрипта, импортированное этой страницей, будет доступно для использования.