Подтвердить что ты не робот

Дизайн API и jQuery

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

Какие части jQuery API могли бы быть выполнены лучше, , как могли бы быть реализованы разные и почему могла бы быть лучше реализована другая реализация?

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

Из-за необходимости замораживания API в популярных библиотеках jQuery застрял в нем в текущем состоянии, и разработчики отлично справляются. Как видно из недавнего изменения .attr vs .prop, разработчики не имеют гибкости в изменении любого из своих дизайнерских решений (что является позором!).

Один конкретный пример, о котором я могу думать, будет

$.each(function(key, val) { })

vs

$.grep(function(val, key) { })

что достаточно запутывает, что я должен дважды проверить частоту параметров.

Пожалуйста, не сравнивайте библиотеку jQuery с полноценными фреймворками, такими как dojo и YUI, и жалуйтесь на отсутствие функций.

4b9b3361

Ответ 1

  • .load() перегружается совершенно другим поведением в зависимости от переданных аргументов

  • .toggle() перегружается совершенно другим поведением в зависимости от переданных аргументов

  • возможно слишком большая перегрузка функции jQuery().

  • the .attr() вы упомянули. Отличие от свойств должно было быть немедленным IMO.

  • .map( key,val ), но $.map( val,key ), а значения this различны.

  • нестандартные селектора должны быть исключены из Sizzle IMO. Механизмы селектора на основе Javascript должны устаревать в течение нескольких лет, и люди, подключенные к проприетарным селекторам, будут иметь более сложный переход

  • плохой метод имен таких методов, как .closest() или .live(). Что именно они делают?

  • Недавно я обнаружил, что вы не можете устанавливать стандартные атрибуты width и height через аргумент props при создании нового элемента. Вместо этого jQuery запускает собственные методы width и height. IMO, атрибутам spec должно быть присвоено приоритетное значение, тем более что width и height могут быть установлены через css.

$('<img/>', { 
    css:{width:100, height:100},
    width:100, // <-- calls method, why?
    height:100, // <-- calls method, why?
});
  • $.get() и .get() совершенно разные.

  • .get() и .toArray() идентичны при передаче аргументов

  • toArray() и $.makeArray() делают то же самое. Почему они не дали им то же имя, что и .each() и $.each()?

  • два разных метода делегирования событий. .delegate() разумный, и .live() магический "вау, он просто работает!" один.

  • .index() перегружен тремя поведением, но их различия могут запутать

 // v---get index   v---from collection (siblings is implied)
$('selector').index();
 // v---from collection   v---get index
$('selector').index(element);
 // v---get index      v---from collection
$('selector').index('selector');

Первое понятно, если вы помните, что он работает только с первым элементом

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

Третий полностью запутан. Этот метод не дает указания, какой селектор является коллекцией и какой селектор представляет элемент, индекс которого вы хотите получить из коллекции.

Почему бы не просто устранить третий, и попросите людей использовать второй такой:

 // v---from collection      v---get index
$('selector').index( $('selector') );

Таким образом, он более тесно связан с остальной частью jQuery, где .index() работает со всей коллекцией.

Или, по крайней мере, изменить смысл селекторов, чтобы они лучше вписывались:

 // v---from collection   v---get index
$('selector').index('selector');

Здесь еще нужно подумать.

У меня есть некоторые проблемы с обработкой событий jQuery/системой хранения данных. Он восхваляется, потому что он не добавляет функции к свойствам on[event], которые могут закрываться вокруг других элементов, создавая утечки памяти в IE. Вместо этого он размещает легкое свойство expando, которое сопоставляется с записью в jQuery.cache, которая содержит обработчики и другие данные.

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

Независимо от того, какая система не имеет значения. Дело в том, что связь между элементом (элементами) и jQuery.cache заключается в том, что expando.

Почему это очень важно? Ну философски jQuery не является основой; это библиотека. Похоже, что в качестве библиотеки вы сможете использовать или не использовать функции jQuery без заботы о негативных эффектах. Тем не менее, если вы выходите за пределы jQuery при удалении элементов из DOM, вы оспариваете любые обработчики и другие данные, связанные с этими элементами, через расширение, создавая приятную и полностью кросс-браузерную утечку памяти.

Так, например, что-то простое, как el.innerHTML = '' может быть очень опасным.

Смешайте это с функцией jQuery.noConflict(). Это позволяет разработчикам использовать jQuery с другими библиотеками, использующими глобальное пространство имен $. Что ж, если одна из этих библиотек удалит некоторые элементы? Та же проблема. У меня такое ощущение, что разработчик, который должен использовать библиотеку типа Prototypejs вдоль боковой jQuery, вероятно, не знает достаточного количества JavaScript для принятия правильных проектных решений и будет подвержен такой проблеме, как я описал.


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

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

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

Поскольку jQuery настолько доминирует, я думаю, было бы хорошо, если бы они не только упростили работу с JavaScript/DOM, но и помогли вам стать лучшими.

Ответ 2

Способ, которым jQuery обрабатывает коллекции по сравнению с отдельными элементами, может быть запутанным.

Скажем, если бы мы обновили некоторое свойство css в наборе элементов, мы могли бы написать

$('p').css('background-color', 'blue');

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

$('p').css('background-color')

MooTools вернет массив, содержащий цвета фона каждого соответствующего элемента, что кажется более интуитивным.

Соглашения об именах для jQuery упрощают лаконичность, а не ясность. Мне нравится стратегия Apple при именовании вещей:

Лучше быть ясным, чем кратким.

И вот пример имени метода из изменяемого класса массива (NSMutableArray) в Objective-C.

removeObjectAtIndex:(..)

Он не пытается быть умным о том, что нужно удалить или куда его удаляют. Вся информация, которую вам нужно знать, содержится в названии метода. Сравните это с большинством методов jQuery, таких как after и insertAfter.

Если кто-то может интуитивно выяснить, что делает after или insertAfter, не читая документы или исходный код, тогда этот человек является гением. К сожалению, я не один - и на сегодняшний день я все еще должен пойти в документацию, чтобы выяснить, что, черт возьми, помещается туда, где при использовании этих двух методов.

Ответ 3

Включено в jquery:

.post()
.get()
.getScript()
.getJSON()
.load()

Не в jQuery:

$.getXML();
$.headXML();
$.postXML();
$.putXML();
$.traceXML();
$.deleteXML();
$.connectXML();
$.getJSON();
$.headJSON();
$.postJSON();
$.putJSON();
$.traceJSON();
$.deleteJSON();
$.connectJSON();
$.headScript();
$.postScript();
$.putScript();
$.traceScript();
$.deleteScript();
$.connectScript();
$.getHTML();
$.headHTML();
$.postHTML();
$.putHTML();
$.traceHTML();
$.deleteHTML();
$.connectHTML();
$.getText();
$.headText();
$.postText();
$.putText();
$.traceText();
$.deleteText();
$.connectText();
$.head();
$.put();
$.trace();
$.delete();
$.connect();

Почему меня это беспокоит? Не потому, что у нас нет вышеуказанных методов в библиотеке, это просто глупо, и я ненавижу, если мы когда-либо (плюс, большинство не будет работать с браузерами), но я ненавижу эти короткие методы место: $.post(); Отправляет запрос ajax через сообщение.

Знайте, что покрывает все в этом списке? Единственная функция, которая не является короткой, $.ajax, она полнофункциональна и покрывает все, вы даже можете настроить ее для хранения значений по умолчанию и, по сути, создать все эти короткие руки. Вы можете создать свои собственные методы, если хотите называть этот вызов ajax (что и все они делают).

Здесь, где это действительно ДЕЙСТВИТЕЛЬНО раздражает.

Кто-то пишет весь свой код, используя сокращенное обозначение:

$.getJSON(
  'ajax/test.html', 
   function(data) {
     $('.result').html(data);
   }
);

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

$.ajax({
  type: 'POST',
  url: url,
  data: data,
  success: success
  dataType: dataType
});

Ой, подождите, я не могу просто заменить слово, вся структура повсюду.

Это и особенно для таких вещей, как $.load(), перекрестные строки, в которых PHP имеет такой ненавистный API, они пытаются делать то, что не должны делать.

Чтобы расширить это за пределами вызовов AJAX, посмотрите фрагмент анимации. У нас есть вызовы slideUp, slideDown, fadeIn, fadeOut, fadeToggle, show и hide. Зачем? Где мой слайд слева, скользить вправо, скользить, выдвигаться, телепортироваться и все, что мы можем придумать? Почему бы не просто придерживаться $.animate() и позволить кому-то писать плагин, если мы хотим получить эти эффекты. Infact, кто-то написал плагин, jQueryUI расширяет анимацию. Это просто безумие и приводит к тому, что люди не знают, что некоторые эффекты создают правила CSS в своих div, которые в конечном итоге сворачивают то, что они хотят сделать позже.

Держите его в чистоте, сохраняйте его простым.

Ответ 4

patrick dw поразил большинство пунктов в своем (фантастическом) ответе. Просто добавьте в свою коллекцию еще несколько примеров.

Предполагается, что API должен быть последовательным; и jQuery преуспевает во многих областях (будучи очень последовательным для возвращения объекта jQuery/получения значения, как и ожидалось во многих случаях). Однако в других ситуациях это не так хорошо.

Имена методов Как уже указывал Патрик; ближайший() - это имя метода дерьма. prev() и next() появляются как если бы они выполняли работу prevAll() и nextAll().

delay() смущает много людей: В следующем примере, который вы ожидаете? (что на самом деле происходит?)

$('#foo').hide().delay(2000).slideDown().text('Hello!').delay(2000).hide();

Аргументы методов Многие функции обхода дерева не согласуются с тем, что они принимают; все они принимают смесь селекторов, объектов и элементов jQuery, но ни одна из них не является последовательной; что плохо, учитывая, что все они выполняют аналогичные задания. Проверьте ближайший(), find(), siblings(), родители(), parent() и сравните различия!

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