Мне было интересно, необходима ли window.onload = function(){}
(или любая другая загрузка, например jQuery $(document).ready();
, если код помещен внизу моего <body>
?
Или могут быть очень неожиданные побочные эффекты?
Мне было интересно, необходима ли window.onload = function(){}
(или любая другая загрузка, например jQuery $(document).ready();
, если код помещен внизу моего <body>
?
Или могут быть очень неожиданные побочные эффекты?
Да, могут быть неожиданные последствия. Но нет, это совершенно не обязательно. Время может быть отключено для вещей, которые все еще загружаются, таких как сложные макеты, глубокие структуры DOM, динамический HTML из других скриптов или изображения. Чтобы избежать таких ситуаций, всегда безопаснее обернуть сценарий событием onload
.
Вот несколько примеров, демонстрирующих это. Все примеры протестированы на Chrome 17.0.963.12 dev в OS X. Результаты браузера могут отличаться, если не используется onload
, что демонстрирует его непредсказуемое поведение. Примеры возвращают fail
, если результат отличается от ожидаемого (т. е. того, что указано в вашем проекте), и возвращают success
, когда результат соответствует ожидаемому. С onload
они всегда возвращают success
.
В этом примере код ожидает, что изображение будет иметь определенную ширину. Если код заключен в событие onload
, ширина правильная, иначе — нет.
Демонстрация: http://jsfiddle.net/ThinkingStiff/qUWxX/
HTML:
<div id="result"></div>
<img id='image' src="http://thinkingstiff.com/images/matt.jpg" />
Скрипт:
document.getElementById( 'result' ).innerHTML
= document.getElementById( 'image' ).offsetWidth == 346 ? 'success': 'fail';
Вы увидите, что для jsFiddle установлено значение «onLoad» в верхнем левом углу страницы, а результат над изображением — success
.
Измените это на «onDomReady» или «без переноса (тело)»:
Теперь нажмите «Выполнить» в левом верхнем углу страницы:
Результат над изображением теперь будет fail
.
Вот еще один пример, в котором не используются изображения. В этом случае встроенный скрипт был добавлен в HTML. Код ожидает, что ширина будет такой, какой она была установлена встроенным скриптом. С onload
правильно, без - нет. Используйте те же инструкции, что и раньше для этой демонстрации.
Демонстрация: http://jsfiddle.net/ThinkingStiff/n7GWt/
HTML:
<div id="result"></div>
<div id="style"></div>
<script>
window.setTimeout( function() {
document.getElementById( 'style' ).style.width = '100px';
}, 1 );
</script>
Скрипт:
document.getElementById( 'result' ).innerHTML
= document.getElementById( 'style' ).style.width ? 'success' : 'fail';
Вот пример, в котором не используются изображения или Javascript в теле, только CSS. Опять же, результаты различаются между onload
и нет.
Демонстрация: http://jsfiddle.net/ThinkingStiff/HN2bH/
CSS:
#style {
animation: style 5s infinite;
-moz-animation: style 5s infinite;
-ms-animation: style 5s infinite;
-o-animation: style 5s infinite;
-webkit-animation: style 5s infinite;
border: 1px solid black;
height: 20px;
width: 100px;
}
@keyframes style { 0% { width: 100px; } 100% { width: 500px; } }
@-moz-keyframes style { 0% { width: 100px; } 100% { width: 500px; } }
@-ms-keyframes style { 0% { width: 100px; } 100% { width: 500px; } }
@-o-keyframes style { 0% { width: 100px; } 100% { width: 500px; } }
@-webkit-keyframes style { 0% { width: 100px; } 100% { width: 500px; } }
HTML:
<div id="result"></div>
<div id="style"></div>
Скрипт:
document.getElementById( 'result' ).innerHTML
= document.getElementById( 'style' ).clientWidth > 100 ? 'success' : 'fail';
Слишком много сценариев, когда отсутствие упаковки кода может вызвать проблемы, которые вы не сможете предвидеть. Чтобы избежать таких ситуаций, всегда безопаснее обернуть сценарий событием onload
.
DOMContentLoaded
. Конечно, вам понадобится обработчик load
, если сначала нужно загрузить ресурсы, отличные от DOM.
- person Jeffrey Sweeney; 03.01.2012
async
или defer
как способ ускорить процесс? Или они начинают добавлять разные файлы сценариев для подключаемых модулей jQuery, которые создают динамический HTML? Утверждение, что это всегда безопаснее... неверно? Когда небезопасно использовать .onload
?
- person ThinkingStiff; 03.01.2012
DOMContentLoaded
(или onload
для внешних ресурсов) небезопасно, а только в том, что в этом нет необходимости.
- person Jeffrey Sweeney; 03.01.2012
DOMContentLoaded
и дополнительно уточнил всегда использовать.
- person ThinkingStiff; 04.01.2012
DOMContentLoaded
и дополнительно уточнил onload
.
- person ThinkingStiff; 04.01.2012
fail
просто означает, что onload
и no wrap
действуют по-разному. Поскольку результаты разные (по крайней мере, в браузере, который я тестировал), ваш код может ожидать один результат, а вместо этого выдает другой. С onload
вы всегда получаете один и тот же ожидаемый результат: ширина, высота, расположение — все именно то, что вы установили в своих проектах.
- person ThinkingStiff; 04.01.2012
body
должно выполнять свою работу. Ваш второй пример также не выглядит как реальный жизненный сценарий (я понимаю, но ... setTimeout?, если интервал был немного больше, onLoad тоже не помогает).‹br› Я вообще не понимаю вашу точку зрения.
- person Boris D. Teoharov; 26.05.2013
Происходит несколько разных вещей.
onload
вызывается только после загрузки встроенного содержимого, например изображений. Это означает, что вы можете поместить код в onload
, который зависит от наличия этого контента.Технически сценарии, запускаемые в конце документа, могут использовать такие методы, как getElementById
, для извлечения уже обработанных элементов. Вы все еще можете поместить их в обработчик готовности или загрузки по вышеуказанным причинам. Это не означает, что сами скрипты не должны быть внизу — их присутствие все же дает преимущество для воспринимаемой производительности.
Тег скрипта в нижней части HTML-страницы эквивалентен DOMContentLoaded
. Весь html-код загружен, и теперь Javascript может обращаться к элементам DOM.
load
вызывается, когда все остальные ресурсы, такие как изображения, полностью загружены.