Vanilla JS vs jQuery 2.0

в 14:56, , рубрики: javascript, jquery, web-разработка, фронтенд, метки: , , , ,
Статья навеяна фреймворком Vanilla.js.

Эпоха старых браузеров уходит в небытие, вряд ли сейчас найдется сознательный человек, использующий ie6,7,8, на зло разработчикам и вопреки техническому прогрессу. Возможно, только по необходимости, например корпоративная система написана под IE6, или лентяи админы издеваются над пользователями и не хотят обновлять/устанавливать новые версии. Тем не менее, статистика использования этих браузеров неумолимо стремится к нулю. Собственно и новая версия jQuery 2.0, отказалась поддерживать устаревшие браузеры(IE 6-8). И тут с релизом jQuery возник вопрос, а для чего же тогда нужен jQuery?

Мое мнение заключается в том, что люди используют jQuery лишь по привычке, или просто не знают базовых вещей javascript и API браузера, который он предоставляет. Чего таить, сам писал на jQuery до того, как освоил javascript…
Но в итоге vanilla одержал верх, на то было много причин, но о некоторых подробнее ниже.

Разберем основные возможности jQuery:

Движок кроссбраузерных CSS-селекторов Sizzle

Что ж, это вполне отличная вещь, вот только для чего? Я думаю, не одному мне встречались проекты/плагины, в которых используется jQuery в 3 местах, таких как $('#my_element').hide().
И для этого люди используете jQuery и тащат его в зависимостях? Ну что же, это их выбор…

Что же в этом случае предлагает vanilla?
Для javascript разработчиков знакомо document.querySelectorAll, встроенный в браузер и появившийся даже в IE8. can i use
Но тут кому-то может стать жалко символов, чтобы писать это каждый раз, благо javascript гибкий язык и позволяет писать различные конструкции, чем можно и воспользоваться.

var $ = document.querySelectorAll.bind(document) 
// для браузеров, поддерживающих bind или самостоятельно написанный bind(пара строк кода)
var $ = function(selector){ return document.querySelectorAll(selector) } 
// будет работать везде, где поддерживается querySelector
Манипуляции и переход по дереву DOM

Для многих пользователей jQuery, остается загадкой то, что же происходит, когда они пишут $('selector') или проводят манипуляции с DOM.
Во всех своих методах jQuery возвращает свой объект обертку jQuery, что позволяет пользователям библиотеки писать цепочки из jQuery вызовов.

Я думаю, что многим знакома картина в проектах:

  $(this).next().val(ui.item.id);
  $(this).next().next().val(ui.item.line);
  $(this).next().next().next().val(ui.item.id);
  $(this).next().next().next().next().next().val(ui.item.person.birth_date);
  $(this).next().next().next().next().next().next().next().val(ui.item.person.weight);
  $(this).next().next().next().next().next().next().next().next().val(ui.item.person.height);
  $(this).next().next().next().next().next().next().next().next().next().val(ui.item.person.name_translit);

Конечно, многие скажут, что этому коду прямая дорога на одноименный сайт, и будут правы. В идеале, конечно, next(selector). Но следует задуматься, почему кто-то написал его именно так? А ведь это, типичное поведение для jQuery объектов. Но если не придираться к самому коду, ведь вместо next могли быть различные манипуляции с DOM (css,attr,find...), записанные в цепочку вызовов, напрашивается вопрос: для чего такая обфускация кода?

Видимо, некоторые пишут код для машины… а не для людей, которым этот код достанется.

Подобно поведение существует и для методов работы с объектами jQuery (node list, array), методы: each, map и др. Необходимость в этих методах была, когда jQuery реализовывал их для старых IE. Во всех современные браузерах есть нативные методы работы с массивами, forEach, map…

Что касательно самого jQuery, пример кода:

$([1,2,3]).each(function(index, element){
  //do something
})

$([1,2,3]).each(function(i,e){ console.log(this===e) }) // 2

Сразу несколько замечаний, элемент массива передается вторым аргументом, что в итерации по списку глупо и нелогично, потому как сам итератор нужен чаще чем индекс, а индекс и вовсе не нужен, но есть this который ссылается на текущий элемент, причем в данном случае, создавая новый экземпляр переменной Number… что показано во 2 примере, очевидно что this и атрибут — не одно и то же. При попытке сравнить this с числом, без преобразования, получится false.
javascript, позволяет, но если каждый будет делать так, как ему того хочется, мир от этого явно лучше не станет.

И пример vanilla:

[1,2,3].forEach(function(element, index){
  //do something
}, [, context])

Параметры в логичном порядке, есть возможность задать контекст исполнения (this), не делая лишних замыканий.

Для манипуляции над DOM объектами существует довольно обширное API, почитать можно на MDN.

События

jQuery предоставляет с виду удобный EventListener, позволяет добавлять эвенты на элементы, селекторы и даже, на несуществующие на странице элементы (live -> on), к сожалению, абсолютно неподдающиеся дебагу и делающие лишние манипуляции. Например, повесить эвент на странице, где элемент отсутствует.

$(function(){
  $('.elements').bind('event', callback)
})

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

Что касательно live методов, а вы точно уверенны в том, что вы пишете и знаете, как оно работает? По существу, элементы на странице не берутся из воздуха, ни что не мешает повесить события, например в результате ajax запроса или по событию, вызвавшему появление элемента. Вызов обработчика события ускорится в несколько раз.

jQuery здесь всего лишь синтаксический сахар, не более.

В ранних версиях IE, эвенты прикреплялись с помощью attachEvent, что затрудняло работу, а jQuery в свою очередь, делал все автомагически, но теперь все браузеры поддерживают EventListener

element.addEventListener('event', callback)

что всегда можно переопределить, написав короткий метод или удобную обертку над эвентами(на строк 20), если хватит знаний javascript.

Визуальные эффекты

Набор простеньких утилит для эффектов которые не всегда нужны… Альтернатива? написать самостоятельно, лишь то, что Вам нужно, об этом в статье про vanilla. Конечно не повод городить велосипеды, но не тянуть же ради 1 метода всю библиотеку.

var s = document.getElementById('thing').style;
s.opacity = 1;
(function fade(){(s.opacity-=.1)<0?s.display="none":setTimeout(fade,40)})();

jQuery

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$('#thing').fadeOut();
</script>
AJAX

Трудно сейчас представить сайт без ajax. Но что же делает jQuery таким особенным в данном случае?
В предыдущих версиях было очевидно, что ajax запрос должен быть кроссбраузерным и реализовываться по разному, в зависимости от браузера пользователя. Но это в прошлом, теперь jQuery лишь добавляет синтаксический сахар для тех, кто в действительности просто не знает, как создать объект XMLHttpRequest. Спорить трудно, намного короче записать:

$.ajax({
  method: 'get',
  url: 'http://habrahabr.ru/',
  success: function(data){
    // Профит?
  }
})

без учета самой jQuery вроде коротко, но современные браузеры поддерживают нативный XMLHttpRequest:

var r = new XMLHttpRequest();
r.open("GET", "http://habrahabr.ru/", true);
r.onreadystatechange = function () {
  if (r.readyState != 4 || r.status != 200) return;
  // Профит?
};
r.send();

что само по себе не сильно выходит за рамки jQuery.ajax.

JavaScript-плагины

Обширная библиотека плагинов на jQuery, слайдеры, скролеры и тд… Клоны библиотек на любой вкус, по запросу в поиске можно найти десятки, а то и сотни идентичных плагинов, отличающихся ничемреализацией и/или автором.
$('selector').сделать_все_как_надо() решает много вопросов, но кто из авторов библиотек может вам дать 100% гарантии, и если что-то пойдет не так, заказчику явно будет не интересно слушать, что виноват Вася Пупкин, зарелизивший баг.

Конечно, Vanilla это не фреймворк, а самый что ни на есть javascript, позволяющий делать все, что необходимо.
Трудно представить, чем поможет jQuery, если вам необходимо написать какой-нибудь класс на javascript или не найдется нужной либы, а вы, возможно, даже и не слышали, что такое prototype(не фреймворк) и для чего он нужен.

Резюме

В итоге нельзя сказать, что jQuery тяжелый фреймворк (33.6 KB сжатый) в наш цифровой век безлимитных интернетов и мобильных устройств с памятью большей 1Гб. Но в большинстве случаев абсолютно бесполезный довесок, замедляющий работу страницы во много раз(как показывают бенчи примерно 50), без которого можно обойтись. Совсем другая ситуация с плагинами. Складывается впечатление, что разработчики вовсе не хотят сами думать, новый таск — новый плагин в проекте. В итоге кол-во плагинов jQuery (которые могут тянуть разные версии jQuery), раздувает js до 0.5 Мб, а то и больше…

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

Известна точка зрения Никлауса Вирта, которую разделяет часть программистского сообщества: согласно ей, любое расширение языка, не вызванное необходимостью, ухудшает его, так как приводит к усложнению транслятора и, соответственно, к понижению его надёжности и производительности. Одновременно возрастает сложность изучения языка и сложность сопровождения программ. Кроме того, сам факт наличия дополнительных синтаксических средств часто играет провоцирующую роль: он побуждает программиста прибегать к различным синтаксическим трюкам вместо того, чтобы глубже анализировать задачу и реализовывать более эффективные алгоритмы.[wiki]

Порой необходимо задумываться над тем, что вы делаете, работа у программиста такая — думать, вот и постарайтесь.
Речь не идет о том чтобы отказаться от jQuery и писать на vanilla, просто не переоценивать его возможности, бездумно используя, где надо и не надо, думаю все помнят про "как сложить два числа в javascript".

P.S. Скорее всего в меня полетит много камней от пользователей jQuery и комментарии о том, что он (фреймворк) уменьшает время разработки, но хочется надеется на сознательность людей и верить, что программисты знают свою работу и умеют думать своей головой.

Автор: Fabel

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js