5 полезных методов jQuery API, о которых вы могли не знать

В статье я расскажу о пяти методах jQuery, которые я нашел для себя полезными и о которых, по моим наблюдениям, мало кто знает.

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


jQuery.grep()

jQuery.grep(array, function(elementOfArray, indexInArray) [, invert]) — как можно догадаться с названия, метод фильтрует элементы массива полагаясь на результат функции (оригинальный массив не изменяется). У jQuery также есть похожий метод .filter() который служит для фильтрации набора найденных элементов.

Пример

Нужно выбрать из массива только числа кратные 3:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
console.log($.grep(arr, function(el){
    return el % 3 === 0
}));
// [3, 6, 9, 12, 15] 


.map()

.map( callback(index, domElement) ) — метод полезен тем, что дает возможность без написания циклов сделать преобразования над выбранными элементами или массивом (для массивов нужно использовать jQuery.map()).
Если функция возвращает null или undefined, то элемент будет проигнорирован.

Пример

Выведем адреса всех ссылок на странице:
var links = $('a').map(function(el){ 
    return this.href;
}).get().join("\n");
console.log(links);


jQuery.proxy()

jQuery.proxy( function, context ) — может быть полезным, если нужно передать callback, но установить для него свой контекст (значение переменной this).

Пример

var myObj = {
    message: 'hello',
    alertMessage: function(){
        // переменная this ссылается на объект myObj, 
        // а не на элемент, по которому кликнули
        alert(this.message);
        return false;
    }
};

$('a').click($.proxy(myObj.alertMessage, myObj));


.prop()

.prop( propertyName, value ) — этот метод появился в версии 1.6 и я использую его примерно с того же времени. Но решил упомянуть здесь потому, что многие ошибочно используют метод .attr() для доступа к свойствам элементов и модификации их значений.
Дело в том, что с версии 1.6 .attr() работает непосредственно с атрибутом элемента и в некоторых случаях результат не совсем ожидаемый.
Например, если мы хотим узнать состояние чекбокса, то .attr() может выдать его значение по умолчанию (которое видно в исходниках HTML страницы). В этом случае нам нужно использовать метод .prop() — он вернет текущее значение свойства элемента.

Пример

Инвертируем все чекбоксы на странице:
$('input').prop('checked', function(el, oldVal){
    return !oldVal;
});


.serializeArray()

.serializeArray() — очень простой способ сеарилизации данных формы в виде массива или строки (в этом случае используйте .serialize()). Метод возвращает массив, который потом например можно через ajax передать на сервер.

Пример

var arr = $('#myForm').serializeArray();
// в arr будет массив объектов {name: "field-name", value: "field-value"}
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 68

    –4
    Спасибо! Очень интересно! map более удобаня замена Each :)
      +11
      map — это не замена each, а другой метод. Это всё-равно, что говорить, что огурцы — отличная замена колбасе.
      В оригинальном JS есть что map, что forEach
        0
        А уж в ECMAScript 6…
          +1
          Я наверное не понял Вашей аллегории,
          и возможно заблуждаюсь насчет jquery

          Разве разница между map и each в Jquery не только в том
          что map возвращает новый объект
          а each исходный?

            +2
            У них разные цели.
            Map позволяет создать новый объект с изменёнными данными (на основе прежних).
            Each позволяет просто пройтись по объекту.
              0
              Согласен с Keyten. Более того, они не совсем взаимоменяемые.
              var $a = $('a');
              
              $a
              .each(function () {
                this.prop = 123;
              })
              .click( activate )
              
              


              В таком примере нельзя each заменить на map. Потому map это не «более удобаня замена Each», а другой метод с другим предназначением.
                +1
                Нельзя потому что map возвращает новый объект.
                Об этом я писал выше.
                  +1
                  Ну так я ж и говорб, что мап — не замена ич.
                  0
                  Этот each вообще не имеет отношения к сабжу. Это другой метод.
                  api.jquery.com/each/ — сабжевый
                  api.jquery.com/jQuery.each/ — ваш
                    0
                    *наоборот конечно
                0
                так а чем же $.map отличается от Array.map?
                  0
                  Array.map не во всех браузерах работает, jQuery должен проверить есть ли этот метод нативный и если нет то использовать свою реализацию.
                    0
                    Ан нет…

                    jquery-1.7.1:
                        // Go through the array, translating each of the items to their
                        if ( isArray ) {
                          for ( ; i < length; i++ ) {
                            value = callback( elems[ i ], i, arg );
                    
                            if ( value != null ) {
                              ret[ ret.length ] = value;
                            }
                          }
                    
                        // Go through every key on the object,
                        } else {
                          for ( key in elems ) {
                            value = callback( elems[ key ], key, arg );
                    
                            if ( value != null ) {
                              ret[ ret.length ] = value;
                            }
                          }
                        }
                    
                      0
                      Упачки, я просто сужу по underscore.
                        0
                        Как мы видим, $.map работает и для объектов.
                +26
                Не хотелось бы выступать в роли К.О., но это просто грех при использовании простых языков/фреймворков — не озаботится хотя бы полным прочтением документации, хотя бы один раз. Просто что бы знать какие функции в принципе там есть.
                Иногда в коде встречаются «новоизобретенные» велосипеды, созданные исключительно по причине не знания о наличии такой функции. И это расстраивает. Можно не знать как используется каждая функция (доки в конце концов под рукой), но хотя бы примерно иметь представление об имеющемся наборе функций — надо.
                  +35
                  зануда
                    +15
                    Я не знаю о половине функций jQuery, но это не мешает мне им пользоваться — просто когда мне что-то надо, я сначала гуглю (или ищу на jqapi) то что мне надо, и только если этого нет по-умолчанию, начинаю писать велосипед.

                    Не обязательно заучивать весь функционал фреймворка, надо просто уметь искать.
                      –1
                      т.е. мне надо получить значение input'а
                      захожу в гугл… ввожу «jquery get input value»… получаю ссылку на $.fn.val() и радуюсь жизни?

                      то же самое с «bind event», «delegate event», «checkbox value» (а тут вам предложат attr который даже не сработает)

                      и весь ваш код в потенциально deprecated функциях. поздравляю!
                        0
                        т.е. мне надо узнать что-то, чего я пока незнаю
                        захожу на jqapi, потом docs.jquery, потом google (note the difference!)… ищу то что мне надо… получаю результат, включаю мозги (важный момент, вы о нем забыли), анализирую его, использую, и радуюсь жизни!

                        то же самое с принципом работы двигателя sabre или самолета hotol (а ведь гугл может выдать результаты которые даже устарели)

                        Весь ваш код, кстати, тоже в потенциально deprecated функциях, которые рано или поздно могут стать неугодными. У вас нигде .live('click', function(){}) уже неиспользуется, да? И конечно же вы его заменили на .on()? Что, правда заменили? Ну надо же! А ничего что on() тоже потенциально deprecated функция? Кто ж его знает что в следующей версии разработчикам придет в голову.

                        Кстати, не забудьте выучить всю конструкцию до последнего винтика и принцип работы каждого узла вашего автомобиля, ведь в случае проблемы механик на техосмотре может вам дать совет, который даже не сработает.
                          –1
                          заходить на сайт с документацией, чтобы чтото найти, это все равно что её полностью пролистать, а значит УЖЕ иметь представление о большинстве функций.

                          пример был преувеличенный, а live у меня вообще почти нигде не использовался, так как есть delegate, что конечно, можно не знать, не изучия API, как вы это делаете.

                          я не призываю изучать всё до винтика, но документацию jQuery можно осилить за 2-3 часа или день, если заодно покопаться в исходниках и понять как именно работают некоторые функции и когда лучше их использовать.

                          и причем тут машина?.. я же не говорю, что знаю наизусть все исходники jQuery (оно мне надо?).
                            0
                            >> заходить на сайт с документацией, чтобы чтото найти, это все равно
                            >> что её полностью пролистать
                            Вообще-то на сайте с документацией для таких вещей есть поиск, поэтому просто что-то найти гораздо быстрее, чем пролистать её полностью
                              –1
                              скажем так, я вообще не верю в начинающих программистов, которые будут искать чтото, только когда это им понадобится. сам таким был хоть и давно.

                              вот зачем, например, такому человеку искать map, когда он вообще не знает о такой технике и пользуется нативными циклами.

                              во-вторых, как я уже указал, часто существует возможность решения проблемы двумя способами. например, нужен был map для объектов, но поиск по ключевым словам выдал each… и разработчик начинает писать велосипед, не читая дальше.

                              в-третьих, если уж действительно большое API, можно ограничиться списком функций с кратким описанием. это нормально. но не забивать же совсем?)
                              0
                              jQuery позволяет писать быстро. Быстро, понимаете? Не изучать jQuery за 21 день, а стартовать прямо сейчас. Вы читаете все доки с выходом каждой новой версии?
                              Может вы и книги по jQuery читаете? )
                        +1
                        Согласен.

                        Именно после прочтения всего jQuery API я открыл для себя некоторые из этих функций.

                        А не знал я о них наверное потому что сразу же начинал писать циклы если нужно было отфильтровать массив или сериализовать форму. И мне не приходило в голову поискать решение в jQuery API.
                          +2
                          И правильно делали, что писали циклы. Они значительно быстрее работают.
                        +24
                        Открыл статью — все ссылки фиолетовые, видимо я уже вхожу в круг избранных
                          +3
                          "… то .attr() может выдать его значение по умолчанию ..."
                          Так может или выдает?
                            0
                            Вытянуто с доков:
                            If using jQuery 1.6, the code if ( $(elem).attr(«checked») ) will retrieve the actual content attribute, which does not change as the checkbox is checked and unchecked. It is meant only to store the default or initial value of the checked property. To maintain backwards compatability, the .attr() method in jQuery 1.6.1+ will retrieve and update the property for you so no code for boolean attributes is required to be changed to .prop(). Nevertheless, the preferred way to retrieve a checked value is with one of the options listed above. To see how this works in the latest jQuery, check/uncheck the checkbox in the example below.


                            Несколько раз перечитал и на сколько я понял — только версия 1.6 возвращает дефолтное значение.
                              0
                              в 1.7 отменили такое поведение. Тем не менее, разницу между Attr и prop знать надо
                                0
                                Разница такая же как и в нативном JS, даже названия методов совпадают
                                elem.attr() = elem.getAttribute()
                                elem.prop() = elem.prop
                                Все проще некуда
                            0
                            Спасибо. Тоже около двух лет пользуюсь jQuery, но с .prop() ни разу не встречалась и .grep() тоже не использовала. Взяла на заметку ))
                              –1
                              Не встречал ещё jQuery любителей, у которых бы не было под рукой iQuery Chearsheet.
                              На пример: oscarotero
                                +2
                                Мне больше вот эта нравится — цвета поспокойнее )
                                Но это шпаргалка, которой больше пользуешься как памяткой, что бы что-то вспомнить.
                                  +2
                                  А мне www.futurecolors.ru/jquery ещё удобнее
                                    0
                                    )) отлично, у меня теперь будет три шпаргалки. И каждая хороша по-своему.
                                      0
                                      Более короткий адрес jqapi.ru (идея названия видать взята с jqapi.com)
                                  0
                                  Спасибо, мне очень интересно было читать.
                                    +1
                                    Мало работал с jQuery (специфика работы связана с использованием «голого» JS), поэтому вопрос к более опытным: а что, действительно можно работать «уже около двух лет» и не испытывать потребности в привязке контекста (например, через описываемый jQuery.proxy(), который только в 1.4 появился) к callback'у, так что подобная информация выясняется «случайно» и об этом вообще «мало кто знает»?
                                      +4
                                      можно работать «уже около двух лет» и не испытывать потребности в привязке контекста

                                      оказывается что да :)
                                      меня всегда выручало это:
                                      var that = this;
                                      $('a').click(function(){
                                         that.doStuff();
                                      });
                                      
                                        0
                                        Я может ошибаюсь, но по-моему это немного другой случай. Как вам в примере ниже поможет $.proxy()?

                                        function_name({
                                          method: function() {
                                            var that = this;
                                            $('a').click(function(){
                                                that.doStuff();
                                            });
                                          }
                                        })
                                        
                                          –1
                                          Да, здесь var that = this; не поможет.
                                          В таких случаях я делал свой вариант proxy c использованием функции apply.
                                            –1
                                            Хотя, если нужный контекст доступен с места, где вызывается function_name, то можно и так:
                                            var that = this;
                                            function_name({
                                              method: function() {
                                                $('a').click(function(){
                                                    that.doStuff();
                                                });
                                              }
                                            })
                                            
                                            0
                                            Точно так же:
                                            function_name({
                                              method: function() {
                                                $('a').click($.proxy(this.doStuff, this));
                                              }
                                            })
                                            


                                            Хотя, я что-то не понимаю, откуда у that в исходном тексте взялся метод doStuff?
                                              –1
                                              Действительно; надо больше спать что бы не тупить (
                                          +2
                                          Запросто.
                                            +1
                                            В underscore есть ещё крутая штука _.bindAll.
                                            +8
                                            Даешь цикл статей «jQuery дайджест»! Описание одного метода каждый день.
                                              +1
                                              Если с примерами на конкретных задачах — то только за.
                                              +2
                                              Конкретно для чекбоксов, на самом деле, гораздо удобнее использовать css селекторы, имхо.

                                              if $('input[type=checkbox]').is(':checked') alert('!');
                                                0
                                                Вы наверное удивитесь, но первые три пункта есть в самом javascript и входят в ES5 (поддерживается во всех последних браузерах).
                                                jQuery.grep(array, fn) => array.filter(fn)
                                                jQuery.map(array, fn) => array.map(fn)
                                                jQuery.proxy(fn, context) => fn.bind(context)
                                                

                                                При этом filter/map принимает в качестве первого аргумента функцию, которой будут передаваться item, index и array (сам массив), а в качестве второго аргумента передается контекст — что более гибко и полезно.
                                                  0
                                                  Увы, IE 6-8 не даёт покоя :(
                                                    0
                                                    > Вы наверное удивитесь
                                                    Нет, не удивлюсь.

                                                    О array.filter и array.map я знал. Но они не поддерживаются IE < 9.
                                                    А для fn.bind ситуация с поддержкой браузерами немного хуже хуже.

                                                    Кстати, чем мне нравится jQuery.map — так это тем, что возвращая null или undefined можно избавится от элемента, а array.map просто поставит на то место null или undefined.
                                                  +6
                                                  Я предпочитаю этим $.map/$.grep библиотеку underscore.js в которой есть гораздо больше полезных list-processing функций. А $.proxy = _.bind. Вообще не очень понимаю в этом плане подхода jQuery. Уж лучше бы или весь боевой набор из underscore.js запихали себе, или бы не начинали. А то, похоже, их добавляют по мере того как авторам самим надоедает писать вручную соответствующий код. Сейчас получается, например, что $.map умеет обходить объекты (не массивы), а $.grep — нет. Функций вроде all, any, reduce нет вообще. В результате всё равно приходится подключать дополнительно underscore, ну и для единого стиля не пользоваться аналогами из jQuery.
                                                    +1
                                                    А я отлично понимаю их подход. map и reduce используются внутри jQuery, они уже грузятся каждый раз, хочешь ты этого или нет. Можно было бы не добавлять их в API, лежали бы мертвым грузом. Только спрашивается зачем?

                                                    Deferred и callbacks тоже добавили в API потому что они уже используются внутри jQuery.
                                                      +1
                                                      Да.

                                                      Хорошо, что при обсуждении Undescore-подобных методов jQuery lany припомнил Underscore. А не то вдруг кто-нибудь про Underscore впервые слышит, а тут ему польза.

                                                      Но было бы не очень хорошо, кабы Underscore добавили в jQuery целиком. Потому что ещё бывают такие частные случаи, в которых jQuery нужно использовать, а Underscore низачем не пригождается. Опять же Underscore развивается отдельно, и была бы непременная задержка интеграции и проблемы с какими-нибудь взаимными несовместимостями.
                                                        0
                                                        > Потому что ещё бывают такие частные случаи, в которых jQuery нужно использовать, а Underscore низачем не пригождается.

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

                                                        Конечно синхронизировать два проекта тяжело, но авторы могли бы договориться так что ребята из underscore получили бы возможность коммитить в репозиторий jQuery. Тогда они сами могли бы делать две сборки underscore — отдельную и для jQuery.

                                                        Но вообще полная синхронизация необязательна, просто надо добавить сразу разумный набор функций, которые настолько базовые, что в принципе от версии к версии практически не меняются.
                                                          0
                                                          Опять же underscore не такой тяжёлый, поэтому весь jQuery сильно не вырастет из-за него.

                                                          Файл http://code.jquery.com/jquery-1.7.2.min.js занимает 33 673 байта.

                                                          Файл http://documentcloud.github.com/underscore/underscore-min.js занимает 4 777 байтов.

                                                          Стало быть, прирост составит 14%. (Если сборка jQuery — «кастомная», то занимает ещё меньше по объёму, так что тогда и прирост её, вызванный добавлением Underscore.js, окажется ещё существеннее, ещё заметнее.)

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

                                                          Ценою этакой стабильности окажется необходимость (неприятная для сайторазработчика) учить две версии Underscore.js: сперва родную, затем встроенную в jQuery и оттого лишённую недавних изменений. Глядя в changelog, можно ли не видеть, что даже наиболее базовые функции Underscore.js подвергаются изменениям к лучшему?
                                                    +1
                                                    * jQuery 1.6+:
                                                    $(".myCheckbox").prop(«checked», true);
                                                    $(".myCheckbox").prop(«checked», false);

                                                    * jQuery 1.5 and below:
                                                    $('.myCheckbox').attr('checked','checked')
                                                    $('.myCheckbox').removeAttr('checked')

                                                    * Any version of jQuery:
                                                    // Assuming an event handler on a checkbox
                                                    //If you're working with just one element, it will always be fastest to use DOMElement.checked = true.
                                                    if (this.checked) //to check state
                                                      0
                                                      Jquery — Visual QuickStart Guide. Правда старенькая, но читается на раз.
                                                        +1
                                                        Укажите что jQuery.proxy() может использоваться так: jQuery.proxy(obj, fn), где obj — объект, а fn — название метода этого объекта.

                                                        Пример:

                                                        var arr= [1,2,3]
                                                          , join= jQuery.proxy(arr, 'join')
                                                          ;
                                                        
                                                        join(', ') // => 1, 2, 3
                                                        


                                                        Это гораздо удобнее, чем писать каждый раз jQuery.proxy(obj.fn, obj).
                                                          +1
                                                          А ещё в $.proxy можно и с аргументами работать:
                                                          а) аргументы при вызове будут переданы в проксируемый метод (очевидно, но для полноты информации):
                                                          var pfn = $.proxy(context, 'method'); // или вариант из основного текста статьи
                                                          pfn(a, b); // => context.method(a, b);
                                                          

                                                          б) часть аргументов тоже можно проксировать:
                                                          var pfn = $.proxy(context, 'method', a, b); // или вариант первых двух аргументов из основного текста статьи
                                                          pfn(c); // => context.method(a, b, c);
                                                          
                                                          +1
                                                          Не упомянули еще такие классные штуки как $.queue и $.fn.self, также довольно редкие и которые полезно знать.
                                                            +1
                                                            О queue согласен — полезный метод.
                                                            На счет $.fn.self — вроде нету такого. Может имелось в виду .andSelf()?
                                                              +1
                                                              Конечно andSefl() :)! На автомате спутал с jQueryUI — там везде этот self.
                                                            0
                                                            Сижу и не понимаю, как я жил без serializeArray().
                                                              0
                                                              Как раз некоторое время назад ругался с attr(), а тут вот оно как оказывается. Спасибо за статью :)

                                                              Only users with full accounts can post comments. Log in, please.