Дизайн API и jQuery

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

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

  • Javascript Marquee для замены тегов <marquee>
  • Преобразование строки SVG в Base64
  • Загрузочный бутстрап работает только на кнопках, а не на якорях или пролетах
  • Невозможно получить document.execCommand ('undo'), работающий одинаково в браузерах
  • JQuery: проверка наличия следующего элемента
  • Говорят, что все объекты Javascript имеют свойство prototype, но я вижу только foo.prototype, если foo - это функция?
  • Вопрос распространяется как на индивидуальные детали низкого уровня API, так и на детали высокого уровня API. Мы говорим только о недостатках в API, а не о недостатках в дизайне / назначении библиотеки высокого уровня, jQuery по-прежнему представляет собой библиотеку DOM-манипуляций, ориентированную вокруг механизма выбора.

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

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

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

    против

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

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

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

  • Хорошая справочная документация API Javascript, связанная с браузерами и DOM
  • Как очистить этот setInterval
  • Загрузка Youtube API iframe с RequireJS
  • Узнайте, имеет ли пользователь открытый или приватный профиль на instagram с использованием API?
  • Как запустить скрипт casperJS из php API
  • Javascript / PHP Family Tree Builder с несколькими родителями
  • 4 Solutions collect form web for “Дизайн API и jQuery”

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

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

    • Возможно, слишком много перегрузки функции jQuery() .

    • .attr() вами .attr() . Отличие от свойств должно было быть немедленным ИМО.

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

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

    • Плохой метод, .closest() такие методы, как .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() перегружен с 3 поведением, но их различия могут сбивать с толку

      // 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 – это расширение.

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

     removeObjectAtIndex:(..) 

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

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

    Включено в 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, которые в конечном итоге выходят за рамки того, что они хотят сделать позже.

    Держите его в чистоте, держите его простым.

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

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

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

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

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

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

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

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