Когда использовать Vanilla JavaScript против jQuery?

238

Во время мониторинга / попытки ответить на распространенные вопросы о jQuery я заметил, что существуют определенные практики использования javascript вместо jQuery, которые фактически позволяют вам писать меньше и делать ... ну, в общем, столько же. А также может принести выигрыш в производительности.

Конкретный пример

$(this) против this

Внутри события клика, ссылающегося на идентификатор кликаемых объектов

JQuery

$(this).attr("id");

Javascript

this.id;

Существуют ли другие распространенные практики, подобные этой? Где некоторые операции Javascript могут быть выполнены проще, без привлечения JQuery в смесь. Или это редкий случай? (из jQuery "ярлыка", на самом деле требующего больше кода)

РЕДАКТИРОВАТЬ: Хотя я ценю ответы относительно jQuery против простой производительности javascript, я на самом деле ищу гораздо более количественные ответы. При использовании jQuery , в тех случаях, когда было бы лучше (удобочитаемость / компактность) использовать простой javascript вместо использования $(). В дополнение к примеру, который я привел в своем первоначальном вопросе.

jondavidjohn
источник
Я не уверен, что понимаю вопрос. Вы искали мнения о преимуществах использования библиотечного кода, или вы искали дополнительные кросс-браузерные методы, не совместимые с jQuery, сродни this.id?
user113716
1
Судя по ответам, кажется, что все воспринимают этот вопрос как философский, поскольку я намеревался сделать его очень количественным, чтобы почти составить список примеров, подобных тому, который я обрисовал в общих чертах, которые являются общими (неправильными) практиками.
jondavidjohn
78
релевантный doxdesk.com/img/updates/20091116-so-large.gif
коза

Ответы:

207
  • this.id (как вы знаете)
  • this.value(для большинства типов ввода. Единственные проблемы, которые мне известны, это IE, когда свойства a <select>не valueустановлены на его <option>элементах, или радиовходы в Safari.)
  • this.className получить или установить целое свойство класса
  • this.selectedIndexпротив, <select>чтобы получить выбранный индекс
  • this.optionsпротив, <select>чтобы получить список <option>элементов
  • this.textпротив, <option>чтобы получить его текстовое содержание
  • this.rowsпротив, <table>чтобы получить коллекцию <tr>элементов
  • this.cellsпротив, <tr>чтобы получить его клетки (тд и т)
  • this.parentNode чтобы получить прямой родитель
  • this.checkedчтобы получить проверенное состояние checkbox Спасибо @Tim Down
  • this.selectedчтобы получить выбранное состояние option Спасибо @Tim Down
  • this.disabledчтобы получить отключенное состояние input Спасибо @Tim Down
  • this.readOnlyчтобы получить состояние input ReadOnly Спасибо @Tim Down
  • this.hrefпротив <a>элемента, чтобы получить егоhref
  • this.hostnameпротив <a>элемента, чтобы получить домен егоhref
  • this.pathnameпротив <a>элемента, чтобы получить путь егоhref
  • this.searchпротив <a>элемента, чтобы получить строку запроса егоhref
  • this.src против элемента, где допустимо иметь src

... Я думаю, вы поняли идею.

Будут времена, когда производительность имеет решающее значение. Например, если вы выполняете что-то в цикле много раз, вы можете отказаться от jQuery.

В общем, вы можете заменить:

$(el).attr('someName');

с участием:

Выше был плохо сформулирован. getAttributeне является заменой, но он извлекает значение атрибута, отправленного с сервера, и соответствующий setAttributeему устанавливает его. Необходим в некоторых случаях.

Приведенные ниже предложения как бы покрывают это. Смотрите этот ответ для лучшего лечения.

el.getAttribute('someName');

... для прямого доступа к атрибуту. Обратите внимание, что атрибуты не совпадают со свойствами (хотя иногда они отражают друг друга). Конечно там setAttributeтоже.

Скажем, у вас возникла ситуация, когда получили страницу, где нужно развернуть все теги определенного типа. Это быстро и просто с jQuery:

$('span').unwrap();  // unwrap all span elements

Но если их много, вы можете захотеть сделать небольшой нативный DOM API:

var spans = document.getElementsByTagName('span');

while( spans[0] ) {
    var parent = spans[0].parentNode;
    while( spans[0].firstChild ) {
        parent.insertBefore( spans[0].firstChild, spans[0]);
    }
    parent.removeChild( spans[0] );
}

Этот код довольно короткий, он работает лучше, чем версия jQuery, и его легко превратить в функцию многократного использования в вашей личной библиотеке.

Может показаться, что у меня бесконечный цикл с внешним whileиз-за while(spans[0]), но поскольку мы имеем дело с «живым списком», он обновляется, когда мы делаем parent.removeChild(span[0]);. Это довольно изящная функция, которую мы упускаем при работе с массивом (или объектом, похожим на массив).

user113716
источник
2
приятно ... так что в основном оно вращается вокруг этого ключевого слова, которое без особого труда переносится в объект jQuery.
jondavidjohn
1
@jondavidjohn: Ну, есть некоторые исправления, которые хороши в некоторых случаях, например, this.valueкогда в некоторых случаях есть пара особенностей браузера. Все зависит от ваших потребностей. Есть много хороших техник, которые легко без jQuery, особенно когда производительность имеет решающее значение. Я постараюсь думать больше.
user113716
3
Я собирался написать ответ, но вместо этого я добавлю предложения для вашего. Как правило, attr()массово злоупотребляется. Если вы имеете дело только с одним элементом, тогда вам это понадобится редко attr(). Два из моих любимых - путаница вокруг checkedсвойства флажков (всевозможные мистические заклинания вокруг этого: $(this).attr("checked", "checked")и $(this).is(":checked")т. Д.) И аналогично selectedсвойству <option>элементов.
Тим Даун
1
Aaargh, @patrick, noooo: вы рекомендовали getAttribute(). Вам это почти никогда не нужно : он не работает в IE, не всегда отражает текущее состояние и в любом случае это не то, что делает jQuery. Просто используйте свойства. stackoverflow.com/questions/4456231/…
Тим Даун
1
Я использовал JS так долго, и я не знал о className, спасибо.
IAdapter
60

Правильный ответ заключается в том, что вы всегда будете терять производительность при использовании jQuery вместо «старого» нативного JavaScript. Это потому, что jQuery - это библиотека JavaScript. Это не какая-то необычная новая версия JavaScript.

Причина того, что jQuery является мощным, заключается в том, что он делает некоторые вещи чрезмерно утомительными в кросс-браузерной ситуации (AJAX - один из лучших примеров) и сглаживает несоответствия между множеством доступных браузеров и предоставляет согласованный API. Это также легко облегчает такие понятия, как связывание, подразумеваемая итерация и т. Д., Чтобы упростить совместную работу над группами элементов.

Изучение jQuery не заменит изучение JavaScript. У вас должна быть прочная основа в последнем, чтобы вы в полной мере оценили то, что знание первого облегчает вам задачу.

- Отредактировано, чтобы охватить комментарии -

Поскольку комментарии быстро указывают (и я согласен со 100%), приведенные выше утверждения относятся к бенчмаркингу. «Нативное» решение JavaScript (при условии, что оно хорошо написано) превзойдет решение jQuery, которое выполняет то же самое почти в каждом случае (я хотел бы увидеть пример в противном случае). JQuery ускоряет время разработки, что является значительным преимуществом, которое я не хочу преуменьшать. Он обеспечивает легкий для чтения, легкий для понимания код, который некоторые разработчики могут создавать самостоятельно.

По моему мнению, ответ зависит от того, чего вы пытаетесь достичь. Если, как я полагаю, исходя из вашей ссылки на выигрыш в производительности, вам не хватает максимальной скорости работы приложения, то использование jQuery приводит к дополнительным расходам при каждом вызове $(). Если вы предпочитаете удобочитаемость, согласованность, совместимость с различными браузерами и т. Д., То, безусловно, есть причины отдавать предпочтение jQuery над «нативным» JavaScript.

gddc
источник
8
Я хотел бы увидеть пример ситуации, когда jQuery может превзойти реализацию в чистом JS. Независимо от того, что вы делаете, если вы используете jQuery (или любую другую библиотеку в этом отношении), у вас есть накладные расходы, которые неизбежны. Невозможно избежать (хотя и) незначительных накладных расходов, вызванных вызовом $(). Если вы не сделаете этот звонок, вы сэкономите время.
GDCD
16
Плохо написанное домашнее решение, вероятно, будет медленнее. Команда jQuery выполнила несколько высокоэффективных JavaScript в пакете. Смотрите ответ @ Freelancer.
Стивен
3
Плохо написанное решение всегда будет плохо написанным решением, и это не вина языка. Это не меняет того факта, что библиотека будет нести издержки, которых может избежать «нативная» функция, если она будет хорошо продумана.
GDCD
11
@gddc Я думаю, что лучший пример, где jQuery "превосходит" (читай за пределами эталонного теста) чистый JS, заключается в сокращении времени разработки (это огромная ценность для бизнеса) и упрощении экспериментов
Бен
13
Все, что вы написали, верно, но вы остановились на том, что @Ben отмечает выше. JQuery делает разработчика быстрее и надежнее. Посмотрите эту реализацию KillClass (), которую я написал много лет назад и активно использовал. Знаешь что? Это сломано для определенных крайних случаев. Плохой код - плохой код, а неправильный код - неправильный код, но использование jQuery часто заставляет разработчика писать лучше и более правильный код. В большинстве случаев компьютеры достаточно быстрые; это разработчики, которые нуждаются в помощи.
Phrogz
38

Там есть фреймворк, который называется ... о, угадайте, что? Vanilla JS, Надеюсь, вы получите шутку ...: D Он жертвует разборчивостью кода для производительности ... Сравнивая его с приведенным jQueryниже, вы можете увидеть, что получение DOMэлемента IDпочти в 35 раз быстрее. :)

Так что, если вам нужна производительность, вам лучше попробовать Vanilla JS и сделать свои собственные выводы. Может быть, у вас не будет JavaScript, который может повесить графический интерфейс браузера / заблокировать поток пользовательского интерфейса во время интенсивного кода, как внутри forцикла.

Vanilla JS - это быстрый, легкий кроссплатформенный фреймворк для создания невероятных, мощных приложений JavaScript.

На их домашней странице есть несколько сравнений:

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

оборота Лениэль Макафери
источник
1
@Leniel Macaferi О, чувак, мне понравился этот ответ! Я не осознавал, что производительность между vanilla и другими фреймворками может иметь такое значение! В любом случае зал славы за этот ответ !! PS: ты тоже сделал сайт?
Стив
17

Уже есть принятый ответ, но я считаю, что ни один из ответов, набранных непосредственно здесь, не может быть исчерпывающим в своем списке нативных методов / атрибутов javascript, который практически гарантирует межбраузерную поддержку. Для этого я могу перенаправить вас в причудливый режим:

http://www.quirksmode.org/compatibility.html

Это, пожалуй, самый полный список того, что работает и что не работает в любом браузере. Обратите особое внимание на раздел DOM. Читать много, но дело не в том, чтобы прочитать все, а в том, чтобы использовать его в качестве справочного материала.

Когда я начал серьезно писать веб-приложения, я распечатал все таблицы DOM и повесил их на стену, чтобы я сразу понял, что безопасно для использования и что требует взлома. В эти дни я просто гуглю что-то вроде того, quirksmode parentNode compatibilityкогда у меня есть сомнения.

Как и все остальное, суждение в основном зависит от опыта. Я бы не советовал вам читать весь сайт и запоминать все проблемы, чтобы выяснить, когда использовать jQuery, а когда использовать простой JS. Просто будьте в курсе списка. Это достаточно легко для поиска. Со временем у вас разовьется инстинкт, когда простой JS предпочтительнее.


PS: PPK (автор сайта) также имеет очень хорошую книгу, которую я рекомендую прочитать

slebetman
источник
14

Когда:

  1. вы знаете, что существует непревзойденная кросс-браузерная поддержка того, что вы делаете, и
  2. это не значительно больше кода для ввода, и
  3. это не значительно менее читабельно, и
  4. вы достаточно уверены, что jQuery не будет выбирать различные реализации на основе браузера для достижения лучшей производительности, тогда:

использовать JavaScript. В противном случае используйте jQuery (если можете).

Изменить : Этот ответ применяется как при выборе использования jQuery в целом, а не при его исключении, так и при выборе, использовать ли vanilla JS внутри jQuery. Выбор между attr('id')и .idсклоняется в пользу JS, в то время как выбор между removeClass('foo')и .className = .className.replace( new Regexp("(?:^|\\s+)"+foo+"(?:\\s+|$)",'g'), '' )склоняется в пользу JQuery.

Phrogz
источник
3
Я думаю, что OP намеревается использовать jQuery, но задается вопросом, где и когда использовать нативный JavaScript внутри его методов jQuery.
Стивен
.classList.remove('foo')кажется, работает нормально в новых браузерах
Tyilo
3
@Tyilo classList.remove является частью HTML5 ClassList API, который не реализован в IE9, например, caniuse.com/#feat=classlist
corbacho
13

Ответы других были сосредоточены на широком вопросе «JQuery против простого JS». Судя по вашему OP, я думаю, вы просто задались вопросом, когда лучше использовать vanilla JS, если вы уже решили использовать jQuery. Ваш пример является прекрасным примером того, когда вы должны использовать vanilla JS:

$(this).attr('id');

Это медленнее и (на мой взгляд) менее читабельно, чем:

this.id,

Это медленнее, потому что вам нужно раскрутить новый объект JS, просто чтобы получить атрибут способом jQuery. Теперь, если вы собираетесь использовать его $(this)для выполнения других операций, во что бы то ни стало, сохраните этот объект jQuery в переменной и оперируйте этим. Однако я сталкивался со многими ситуациями, когда мне просто нужен атрибут из элемента (например, idили src).

Существуют ли другие распространенные практики, подобные этой? Где некоторые операции Javascript могут быть выполнены проще, без привлечения JQuery в смесь. Или это редкий случай? (из jQuery "ярлыка", на самом деле требующего больше кода)

Я думаю, что наиболее распространенным случаем является тот, который вы описываете в своем посте; люди, $(this)без всякой необходимости заворачивающие объект jQuery. Я вижу это чаще всего с idи value(вместо использования $(this).val()).

Редактировать: вот статья, которая объясняет, почему использование jQuery в этом attr()случае медленнее. Исповедь: украл ее из тега вики, но я думаю, что стоит упомянуть вопрос.

Отредактируйте еще раз: учитывая удобочитаемость / производительность при непосредственном доступе к атрибутам, я бы сказал, что хорошим правилом, вероятно, является попытка использовать его, this.<attributename>когда это возможно. Вероятно, в некоторых случаях это не сработает из-за несоответствий браузера, но, вероятно, лучше сначала попробовать это и воспользоваться jQuery, если он не работает.

Эндрю Уитакер
источник
хах, спасибо за чтение вопроса;) ... так что это более широкое исключение?
jondavidjohn
@jondavidjohn: Честно говоря, я не решаюсь сделать этот звонок. Я думаю, да, как правило, в ваших интересах использовать jQuery из-за проблем с браузерами. Есть и другие примеры, например this.style.display = 'none'. Это лучше чем $(this).hide()? Я бы сказал, что последний лучше читается, но первый, скорее всего, быстрее. Нет ничего плохого в том, чтобы поэкспериментировать самостоятельно, чтобы увидеть, будут ли определенные действия работать в браузерах без jQuery. Обычно это делается перед тем, как обернуть элемент в объект jQuery для выполнения операции.
Эндрю Уитакер
10

Если вас больше всего беспокоит производительность, ваш главный пример - удар по голове. Вызывать jQuery излишне или избыточно, IMHO, вторая основная причина низкой производительности (первая - плохой обход DOM).

На самом деле это не пример того, что вы ищете, но я вижу это так часто, что стоит упомянуть: один из лучших способов повысить производительность ваших jQuery-скриптов - это кешировать объекты jQuery и / или использовать цепочку:

// poor
$(this).animate({'opacity':'0'}, function() { $(this).remove(); });

// excellent
var element = $(this);
element.animate({'opacity':'0'}, function() { element.remove(); });

// poor
$('.something').load('url');
$('.something').show();

// excellent
var something = $('#container').children('p.something');
something.load('url').show();
Стивен
источник
интересно ... приводит ли это разделение реализации и действия к фактору к увеличению производительности обработки? или просто позволяет выполнить действие самостоятельно (делая его менее обремененным, я думаю ...)
jondavidjohn
1
Это, безусловно, приводит к повышению производительности, но только если вы повторно используете выбранный элемент. Итак, в последнем случае var somethingмне не нужно было кэшировать объект jQuery (поскольку я использовал цепочку), но я все равно делаю это по привычке.
Стивен
2
С другой стороны, возьмите тот же пример. Вызов $('.something')дважды означает, что jQuery должен дважды пройти DOM, ища все элементы с этим селектором.
Стивен
2
В первом примере кэширование $(this)уменьшает количество вызовов функции jQuery. Это даст вам наибольшую выгоду в петлевом сценарии.
Стивен
2
@Alnitak Обратите внимание, что elementравно $(this). Это не содержит несколько элементов.
Стивен
8

Я обнаружил, что JS и JQ частично совпадают. Код, который вы показали, является хорошим примером этого. Честно говоря, лучшая причина использовать JQ поверх JS - просто совместимость с браузерами. Я всегда склоняюсь к JQ, даже если я могу достичь чего-то в JS.

Dutchie432
источник
8
Было бы удивительно, если бы не было никакого совпадения, потому что JQuery - это JavaScript.
Симон
6

Это мое личное мнение, но так как jQuery в любом случае является JavaScript, я думаю, что теоретически он не может работать лучше, чем vanilla JS.

Но практически он может работать лучше, чем рукописный JS, поскольку рукописный код может быть не таким эффективным, как jQuery.

Итог - для небольших вещей я склонен использовать vanilla JS, для интенсивных проектов JS мне нравится использовать jQuery, а не изобретать велосипед - это также более продуктивно.

CodeVirtuoso
источник
1
Есть много примеров, когда библиотеки превосходят ванильный JS. Оказывается, многие из встроенных методов-прототипов JS написаны плохо.
Изучение статистики на примере
3

Список живых свойств первого ответа this в качестве элемента DOM довольно полон.

Вам также может быть интересно узнать некоторых других.

Когда это документ:

  • this.formsчтобы получить HTMLCollectionтекущие формы документов,
  • this.anchorsчтобы получить HTMLCollectionвсе HTMLAnchorElementsс nameустановленным,
  • this.linksчтобы получить HTMLCollectionвсе HTMLAnchorElements с hrefустановкой,
  • this.imagesчтобы получить HTMLCollectionвсе HTMLImageElementс
  • и то же самое с устаревшими апплетами как this.applets

Когда вы работаете с document.forms, document.forms[formNameOrId]получает так называемую или идентифицированную форму.

Когда это форма:

  • this[inputNameOrId] чтобы получить так называемое или идентифицированное поле

Когда это поле формы:

  • this.type чтобы получить тип поля

При изучении селекторов jQuery мы часто пропускаем изучение уже существующих свойств элементов HTML, к которым так быстро получить доступ.

lib3d
источник
Упомянутые вами свойства определены в спецификации HTML DOM Level 2 и широко поддерживаются. document.embedsи document.pluginsтакже широко поддерживаются (DOM 0). document.scriptsэто также удобный набор, определенный в спецификации HTML5 и широко поддерживаемый (и Firefox 9+ ).
Роб W
@Robw Итак, список теперь может быть полным, и определенно полезным и быстрым. Спасибо;)
lib3d
2

Как обычно, я опаздываю на эту вечеринку.

Это не было дополнительной функциональностью, которая заставила меня принять решение использовать jQuery, столь же привлекательный, как это было. Ведь ничто не мешает вам писать свои собственные функции.

Это был тот факт, что при модификации DOM нужно было учиться многим трюкам, чтобы избежать утечек памяти (я говорю о вас, IE). Иметь один центральный ресурс, который управлял всеми этими проблемами для меня, написанный людьми, которые были намного лучше, чем JS-программисты, чем я когда-либо буду, и который постоянно пересматривался, пересматривался и проверялся, был послан Богом.

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

И, конечно же, jQuery не исключает использования прямой JS, когда вам это нужно. Я всегда чувствовал, что эти два, казалось, работали без проблем вместе.

Конечно, если ваш браузер не поддерживается jQuery или вы поддерживаете низкоуровневую среду (старый телефон?), Тогда большой файл .js может быть проблемой. Помните, когда jQuery был крошечным?

Но обычно разница в производительности не является проблемой. Это должно быть достаточно быстро. Поскольку гигагерц циклов ЦП расходуется каждую секунду, меня больше заботит производительность моих кодеров, единственных ресурсов разработки, мощность которых не удваивается каждые 18 месяцев.

Тем не менее, я в настоящее время изучаю проблемы доступности, и, видимо, .innerHTML немного нет с этим. JQuery, конечно, зависит от .innerHTML, поэтому сейчас я ищу среду, которая будет зависеть от несколько утомительных методов, которые разрешены. И я могу себе представить, что такая инфраструктура будет работать медленнее, чем jQuery, но пока она работает достаточно хорошо, я буду счастлив.

Swanny
источник
2

Вот нетехнический ответ - многие задания могут не разрешать определенные библиотеки, такие как jQuery.

Фактически, Google фактически не разрешает jQuery ни в одном из своих кодов (ни в React, потому что он принадлежит Facebook), чего вы могли не знать, пока интервьюер не скажет: «Извините, но вы не можете использовать jQuery, он не включен утвержденный список в XYZ Corporation ". Vanilla JavaScript работает абсолютно везде, всегда и никогда не доставит вам этой проблемы. Если вы полагаетесь на библиотеку, да, вы получаете скорость и легкость, но вы теряете универсальность.

Кроме того, если говорить об интервьюировании, то другим недостатком является то, что если вы говорите, что вам нужно использовать библиотеку для решения проблемы JavaScript во время викторины, вы обнаружите, что вы на самом деле не понимаете проблему, что выглядит довольно плохо. Принимая во внимание, что если вы решите это в необработанном ванильном JavaScript, это продемонстрирует, что вы действительно понимаете и можете решить каждую часть любой проблемы, которую они бросают перед вами.

Джек коннор
источник
1

$(this)отличается от this:

Используя его, $(this)вы гарантируете, что прототип jQuery передается объекту.

Джон Грин
источник