Почему jQuery.ready рекомендуется, когда он работает так медленно?

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

При использовании jQuery многие из нас используют функцию jQuery.ready для выполнения init при загрузке DOM. Он стал де-факто стандартным способом добавления программ манипуляции DOM на веб-страницу с помощью jQuery. Связанное событие существует изначально в некоторых браузерах, но jQuery имитирует его в других браузерах, таких как некоторые версии IE. Пример:

<head>
<script>
    var init = function() { alert('hello world'); };
    $.ready(init);
</script>

Теперь все наши тесты показывают, что это событие может быть довольно медленным. Его не так медленно, как window.onload, но его все еще часто около 100 мс задержки перед исполнением. Если FF может быть до 200-300 мс, особенно при обновлении.

Это очень важные миллисекунды, потому что это время, в течение которого начальный макет отображается до того, как будут сделаны какие-либо манипуляции с DOM (например, скрытие выпадающего списка). Много раз макет "мерцание" в основном вызван использованием медленного события готовности DOM, заставляющего программистов скрыть элементы с использованием CSS и потенциально сделать его менее доступным.

Теперь, если вместо добавления тега body мы добавим функцию init в тег script, он будет выполняться намного быстрее, обычно примерно в половине случаев, но иногда даже быстрее:

<head>
<script>
    var init = function() { alert('hello world'); };
</script>
</head>
<body>
<!-- some HTML -->
<script>init();</script>
</body>

Простая тестовая страница, которая доказывает различия: http://jsbin.com/aqifon/10

Я имею в виду, мы говорим не о едва заметных различиях, поскольку некоторые из "оптимизационной полиции" продвигают, когда дело доходит до использования эффективных селекторов. Мы говорим о некоторых серьезных задержках при выполнении манипуляций DOM onload. Попытка этого примера в FF, domready иногда может быть более чем в 100 раз медленнее (300 мс против 2 мс).

Теперь на мой вопрос: Почему jQuery.ready рекомендуется использовать, когда его явно намного медленнее других альтернатив? И каковы недостатки вызова init перед закрытием BODY vs с помощью jQuery.ready? Его возможно более безопасно использовать domReady, но в каком контексте он более безопасен, чем другой вариант? (Я думаю, что такие вещи, как document.write и отложенные сценарии) Мы использовали путь BODY почти на 5 лет на многих клиентских сайтах, и у нас никогда не возникало никаких проблем. Это намного быстрее.

Мне также интересно, так как в jsPerf так много фьюза и оптимизация селекторов за пару мс за 10000 казней, почему не так много говорят об этом? В основном это первая задержка, с которой сталкивается пользователь, и кажется, что довольно просто нарезать 50-100 мс при каждой загрузке страницы...

Ответ 1

В первую очередь:

Нет, нет недостатка в вызове init перед закрытием <body>.. Как вы заметили, лучше выполняйте работу, используя $.ready(), а также будет работать со всеми браузерами безупречно (даже в IE).

Теперь есть причины использовать $.ready(), которые в вашем случае они, вероятно, не применяются:

  • $.ready() упрощает разработчикам работу в правильном порядке. В частности, критически важно не ссылаться на элементы DOM, которые не были загружены. Хотя это достаточно просто, многие разработчики все еще сбивают с толку. $.ready() - без проблем, хотя и медленный.
  • У вас есть несколько сценариев, которые нуждаются в init(), это не всегда удобно/удобно вручную делать это в конце вашего тела. Это требует дисциплины и знаний о том, что делают эти сценарии. В частности, вы часто увидите $.ready() в библиотеках, зависящих от jQuery, поскольку это заставляет все работать независимо от того, каким образом разработчики будут использовать для загрузки libs.
  • С определением асинхронного модуля (например require.js) становится популярным как способ загрузить ваш javascript, конец метода <body/> не гарантируется.

Ответ 2

Одно из преимуществ заключается в том, что вы можете разместить код в любом месте страницы. В нашем случае мы используем систему шаблонов в нашей CMS, которая сшивает страницу вместе с 10-30 шаблонами для разных частей (в зависимости от сложности).

Поскольку вы хотите, чтобы шаблоны работали на любой странице, они используются, вам нужно включить в нее необходимый Javascript. В этих случаях функция ready() является реальной спасательной способностью.

Ответ 3

Если вы написали JS файл, который другие люди включают в свои страницы, безопаснее использовать document.ready внутри этого файла (при условии, что он должен выполнить некоторую обработку автоматически после того, как DOM готов), потому что вы не можете убедитесь, что файл будет включен в голову или в конец тела.

Когда дело доходит до страниц, на которых у вас есть полный контроль, тогда, очевидно, у вас нет такого беспокойства, поэтому я не вижу, что более безопасно использовать document.ready, а не называть ваш init() от конца тела. Использование document.ready(или onload) и размещение script в конце тела - два наиболее распространенных способа сделать это, и они являются общими, потому что они оба хорошо работают.

Вы упомянули document.write() как возможное исключение, но не хотите, чтобы вы вызывали это из document.ready или в конце тела, потому что в любом случае все страницы уже проанализированы.

Ответ 4

Потому что это делает domReady и window.load медленнее.

Легко оптимизировать метрику, а не фактический пользовательский интерфейс. Таким образом, графики "реальной оптимизации пользователей" снижаются, хотя интерактивность задерживается.