Является ли событие DOMContentLoaded ТОЧНО таким же, как функция jQuery.ready()?

Я заменил window.addEventListener('DOMContentLoaded', function() {}); на jQuery $(document).bind('ready', function() {});, потому что первый из них не работал на IE < 9, и я не хотел играть с .attachEvent() для этого фиктивного браузера, если бы у меня это было хорошо покрыто самой jQuery.

Вскоре после замены я заметил, что событие DOMContentLoaded всегда запускалось около 0-2 миллисекунд после загрузки/обновления страницы (по крайней мере, это то, что было зарегистрировано в моем протоколе script), а .ready() всегда требуется на менее 15-20 миллисекунд, после обновления страницы, для запуска (опять же - как зарегистрировано script).

Я прошу только кормить свое любопытство, почему существует такая "значительная" задержка? Конечно, для меня нет проблем, что jQuery запускает это событие позже. Просто, потому что я хочу знать ВСЕ ответы (и править миром!), Я не могу спать с этим!:]

EDIT: в .ready() function doc некоторый пользователь (Nick (из Nexxar)) указывает, что: "jQuery имитирует не существующее событие" DOMContentLoaded "в IE, но используемый механизм срабатывает намного позже, чем событие, используемое в других браузерах". Может быть, это то же самое, я прошу?

Ответ 1

Предполагая браузер, поддерживающий событие:

  • Реальное событие может поддерживать любой document. jQuery будет использовать только document, в который он был загружен, независимо от того, что вы передаете ему.
  • jQuery будет запускать событие асинхронно, даже если это событие уже произошло. Прикрепление события 'DOMContentLoaded' ничего не сделает, если событие уже произошло.

В этих браузерах нет задержек, см. http://jsfiddle.net/rqTAX/3/ (занесенные в записях в миллисекундах).

Для браузеров, которые не поддерживают событие, jQuery, очевидно, будет работать и для них. Он будет использовать хакерский механизм, который не совпадает с реальным DOMContentLoaded и не обязательно будет срабатывать, как только реальный DOMContentLoaded будет:

// The DOM ready check for Internet Explorer
function doScrollCheck() {
    if ( jQuery.isReady ) {
        return;
    }

    try {
        // If IE is used, use the trick by Diego Perini
        // http://javascript.nwbox.com/IEContentLoaded/
        document.documentElement.doScroll("left");
    } catch(e) {
        setTimeout( doScrollCheck, 1 );
        return;
    }

    // and execute any waiting functions
    jQuery.ready();
}

Ответ 2

jQuery имитирует это событие, привязывая к событию document readystatechange, который является стандартным способом моделирования DOMContentLoaded в oldIE.

Согласно источнику jQuery, это событие срабатывает "поздно", но до window.onload. Однако я не могу найти, когда это событие срабатывает точно. DOMContentLoaded срабатывает, когда DOM построен и готов к написанию сценариев, поэтому readystatechange срабатывает после этого; возможно, он ждет рендеринга макета или моделирования чего-то подобного, или событие запускается позже в процессе рендеринга/компоновки?

Несмотря на это, он, скорее всего, срабатывает после DOMContentLoaded, вероятно, из-за того, что IE решит обновить document readyState до "complete."

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

Ответ 3

Еще одна причина того, что "готов" появится позже (на практике), заключается в том, что к нему может быть подключено много событий. Если какие-либо из них являются длительными синхронными операциями, то готовое событие поступит намного позже. Например, я использую knockout.js, и для инициализации страницы может потребоваться 500 мс.


Однако, используя вашу минимальную тестовую страницу, это, конечно, не так. Я попытался запустить следующее:

 console.log(window.performance.timing.domContentLoadedEventEnd -
             window.performance.timing.domContentLoadedEventStart);

Это дает около 6 мс даже для вашей простой супер-страницы


Также я взял ваш код и запустил его с помощью инструментов производительности Chrome и обнаружил несколько интересных вещей:

введите описание изображения здесь

  • BTW: вертикальная синяя полоса DOMCONTENTLOADED, а зеленая - "первая краска".
  • Вы можете видеть, что даже очень простой вызов функции в событии DOMCONTENTLOADED может занимать 5 мс (и это на i7). Помните, что он нуждается в анализе, и что-то нужно инициализировать.
  • Обратные вызовы отображаются в голубом цвете (анонимно), первый - из события DOMCONTENTLOADED, а второй - "готовый" обратный вызов.
  • Вы увидите "Таймер уволен" (т.е. setTimeout). Таким образом, это не мгновенно с помощью каких-либо средств.

Глядя на исходный код jQuery, вы видите, что они фактически устанавливают таймер для обратных вызовов:

// Handle it asynchronously to allow scripts the opportunity to delay ready
window.setTimeout( jQuery.ready );

Я не совсем уверен, что они здесь означают (любая идея), но это объясняет поведение. Я мог видеть, что это полезно для предотвращения условий гонки и блокировки пользовательского интерфейса, но "отсрочка готовности" для меня неясна.