Почему функция селектора jQuery настолько медленна по сравнению с собственными методами DOM

Я знаю, что эта тема обсуждалась в целом уже несколько раз, но я ищу более подробную техническую и подробную информацию, чтобы понять, что происходит на самом деле.

Я разработал серию тестов, чтобы сравнить скорость jQuery самых основных селекторов "#id" и ".class" с различными собственными методами DOM.

Я хочу, чтобы выяснить, почему результаты являются тем, чем они являются.

Вот тесты: http://jsperf.com/jqueryspeed

Самое главное, что getElementById является самым быстрым из всех. Для сравнения я добавил как jQuery ('# id'), так и jQuery.fn.init('# id') в качестве тестов, разница между ними заключается в том, что первый из них запускает целый новый объект jQuery, а второй запускает только прототипную функцию и, следовательно, быстрее. Таким образом, разница между этими двумя понятна.

Основное отличие, которое я НЕ понимаю, это огромный разрыв между скоростью getElementById и скоростью jQuery.fn.init, который имеет простой тест для обработки простого ('#id') запроса в конкретным способом, возвращаясь к вызову getElementById.

Итак, почему, например, в Chrome, этот метод примерно в 8 раз медленнее, чем исходный, хотя он в основном является для него только оболочкой?

Он также примерно в 3-4 раза медленнее, чем обернутый getElementById $(document.getElementById('# id'))...

Любые идеи, пожалуйста?

Ответ 1

Это количество кода, через которое проходит jquery, когда мы используем простой $ ('селектор')

http://james.padolsey.com/jquery/#v=1.10.2&fn=init

Как видите, много проверок, совпадений с регулярными выражениями, кросс-браузерных трюков и т.д.

Важно понимать, что jquery - это библиотека, построенная на javascript. Javascript выполняется непосредственно в браузере. Где jquery обрабатывает довольно много кода javascript перед его выполнением браузером.

Я лично предпочитаю jquery. Я действительно не беспокоюсь о том, чтобы экономить эти нано секунды. Уровень простоты, который обеспечивает jquery, феноменален и сам по себе является произведением искусства.

Ответ 2

Нет ничего, что jQuery может сделать так же быстро, как нативный javascript, и это не просто так: он делает все возможное, чтобы сделать ваш код кросс-браузерным и простым в использовании. Он строит объект jQuery из большинства вызовов методов. В этом отношении jQuery будет намного медленнее, чем наименьший требуемый путь к данным, потому что он хочет предложить функции, которые готовы к использованию.

Давайте сравним эти два "похожих" вызова:

document.getElementById("box"): собственный метод, который выполняет простую операцию поиска на более низком уровне, чем JavaScript. Затем он возвращает элемент DOM, который уже загружен в память. Это один из самых быстрых методов.

$('#box'): Здесь jQuery начнется с некоторого анализа того, что вы просите его сделать. Например, он подтвердит, что это правильно сформированный селектор, а затем попытается распознать, какой это тип селектора. По завершении проверки он попытается получить элемент с идентификатором "box". После этого он создаст новый объект jQuery, заполнив его каждым ожидаемым атрибутом и убедившись, что все браузеры (и более старые браузеры тоже) получают одинаковые результаты. Это включает в себя множество откатов и тестов на соответствие. Когда объект готов к использованию, вы получаете элемент с идентификатором "box". Не так просто, как getElementById(). Когда функции jQuery не требуются для целевого элемента, многие предпочитают использовать getElementById('box') вместо $('#box').


ОБНОВЛЕНИЕ - 15/02/17:

Поскольку jQuery> = 2.0 больше не поддерживает печально известный IE 6/7/8, некоторые тесты совместимости больше не нужны, что делает jQuery легче и быстрее. Общая производительность может быть улучшена с помощью jQuery> = 2.0 вместо 1.x, если вам не требуется поддержка старых браузеров.

Ответ 3

Я добавил еще один тестовый пример для jQuery.fn.init(document.getElementById('id')), который был быстрее, чем большинство других методов, потому что он не выполняет ни синтаксического анализа, ни создания нового объекта jQuery (он был на 50% ниже getElementById, jsperf), и когда я вижу источник кода jquery, который выполняется во время вызова jQuery.fn.init:

function (selector, context, rootjQuery){
  if (selector.nodeType) {
          this.context = this[0] = selector;
          this.length = 1;
          return this;
  }
}

Я могу только заключить, что инженеры Chrome и Firefox отлично справились с оптимизацией собственных операций DOM.