Underscore.js — библиотека, которая так хороша, что должна быть вне закона

    Каждый, кому приходилось писать объемные куски осмысленного кода на javascript, рано или поздно понимал, что ему многого не хватает в этом языке или просто неудобны некоторые врожденные конструкции. Для сглаживания шероховатостей применяются jQuery, Prototype, MooTools etc. Кто-то уже мало представляет себе, как можно кодить без них. Сегодня я расскажу о еще одной маааленькой библиотечке, которая делает мир javascript-программиста еще прекраснее. Речь пойдет о Underscore.js

    Underscore.js или просто _.js — это набор функций-утилит, к которым привыкли любители функционального программированя, Ruby, Python или Prototype.js (но, в отличие от Prototype эта библиотека не расширяет базовые классы JavaScript). Она была написана, чтобы хорошо уживаться с jQuery.
    Underscore.js предоставляет более 60 функций. Часть из них рассчитана на любителей map-reduce, другая — специальные вспомогательный функции для javascript. Библиотека умеет делегировать вызовы, если какая-то функциональность реализована разработчиками браузеров.

    Вот список функций, который в ней реализован и примеры из официальной документации:

    Работа с коллекциями
    each, map, reduce, reduceRight, detect, select, reject, all, any, include, invoke, pluck, max, min, sortBy, sortedIndex, toArray, size
    Примеры
    // Map & Reduce
    _.map([1, 2, 3], function(num){ return num * 3 }); // => [3, 6, 9]
    var sum = _.reduce([1, 2, 3], 0, function(memo, num){ return memo + num }); // => 6
    // Любой из элементов массива true
    _.any([null, 0, 'yes', false]); //=> true
    // Все элементы массива true
    _.all([true, 1, null, 'yes']); // => false
    // Вытаскиваем массив значений по ключу
    var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}];
    _.pluck(stooges, 'name'); // => ["moe", "larry"]


    Работа с массивами
    first, rest, last, compact, flatten, without, uniq, intersect, zip, indexOf, lastIndexOf, range
    Примеры
    // Первый элемент массива
    _.first([5, 4, 3, 2, 1]); // => 5
    // Последний элемент массива
    _.last([5, 4, 3, 2, 1]); // => 1
    // Убрать неугодные элементы
    _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
    // Оставить только уникальные элементы
    _.uniq([1, 2, 1, 3, 1, 4]); // => [1, 2, 3, 4]


    Работа с функциями
    bind, bindAll, memoize, delay, defer, wrap, compose
    Примеры
    // Кэшируем результаты вычислений функции
    var fibonacci = function(n) {
    return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
    };
    var fastFibonacci = _.memoize(fibonacci);


    Работа с объектами
    keys, values, functions, extend, clone, tap, isEqual, isEmpty, isElement, isArray, isArguments, isFunction, isString, isNumber, isBoolean, isDate, isRegExp isNaN, isNull, isUndefined
    Примеры
    // Вытащить имена свойств
    _.keys({one : 1, two : 2, three : 3}); // => ["one", "two", "three"]
    // Вытащить значения свойств
    _.values({one : 1, two : 2, three : 3}); // => [1, 2, 3]
    // Копируем свойства одного объекта в другой
    _.extend({name : 'moe'}, {age : 50}); // => {name : 'moe', age : 50}


    Утилиты
    noConflict, identity, times, breakLoop, mixin, uniqueId, template
    Примеры
    // Удобно и привычно
    _(5).times(function(){ console.log('Odelay!"); });


    Для последовательных вызовов
    chain, value

    Названия говорят сами за себя. Документацию можно найти здесь, там очень хорошие и понятные примеры. Я думаю, что даже незнание английского никого не остановит. Но если есть большая потребность, то можно перевести на русский.
    Стоит добавить, что в сжатом виде библиотека весит 2.9кб, а исходники лежат на GitHub.

    Upd. Добавил немного примеров.
    Поделиться публикацией

    Похожие публикации

    Комментарии 51
      –30
      Не могли бы вы привести пример использования этой библиотеке и объяснить, что же в ней такое есть, чего вам так не хватало при работе с jQuery.
        +21
        JQuery ориентивана на возню с HTML, Underscore же, очевидно из заголовков, ориентирована на упрощение работы с массивами, объектами, функциями, и так далее.
        Документацию и примеры можно найти по ссылке.
        Anonym, вы, наверно, без глаз.
          –12
          Да вроде с глазами, просто я, прочитав топик, подумал, что отлично обхожусь без всего этого, вот и решил поинтересоваться.
            +17
            Некоторые и без jQuery «отлично обходятся™».
            А некоторые даже без Javascript! :)
              +5
              ™ — wapedia.mobi/ru/%D0%A2%D0%9C
              Зачем вы поставили этот символ?
                +9
                Из хулиганских побуждений, конечно.
                +1
                Некоторые и без компьютера отлично обходятся и вообще искренне не понимают красноглазых товарищей ;-)
            +2
            Эта библиотека нужна для того, чтобы повысить удобство при обработке данных в javascript. В том же jQuery реализована от силы пара функций из приведенных выше. И, по заверениям авторов, их версия работает быстрее.
              +2
              простой пример
              ширина блоков
              jquery
              Array.prototype.sum = function(){
              for(var i=0,sum=0;i<this.length;sum+=this[i++]);
              return sum;
              }
              $.makeArray($('.selector').map(function() { return $(this).width() })).sum()

              или
              var sum = 0;
              $('.selector').each(function() { sum += $(this).width() });


              + Underscore.js
              _.reduce($('.selector'), 0, function(m, el){ return m + el.width() });
              –2
              Шел jQuery через jQuery
              Видит jQuery в jQuery jQuery
              Сунул jQuery руку в jQuery
              jQuery, jQuery, jQuery, jQuery
                +6
                www.doxdesk.com/img/updates/20091116-so-large.gif
                Я просто оставлю это здесь
                –1
                как раз недавно надо было манипулировать с массивами так же как в примере! автору статьи респект! будем юзать.
                  –2
                  Эх, засунуть бы все это в jQuery…
                    0
                    напишите плагин
                      +8
                      религия не позволяет писать _.блабла() вместо $.блабла()?
                        +3
                        религия не позволяет писать _( $( '.user' ) )
                      +3
                      Хм, для чего это там? Это отдельный инструмент, ничего не мешает в случае необходимости использовать совместно.
                        –16
                        Это будет как-то не тру.

                          0
                          Не тру будет смешивать компот с супом.
                        +1
                        Отличная библиотека. Узнал о ней около года назад, с тех пор пользуюсь. Javascript made easy! )
                          0
                          Спасибо за статью. Прощайте, велосипеды!
                            0
                            just cool
                              –2
                                +1
                                там допущена та же ошибка, что и в прототайпе: habrahabr.ru/blogs/javascript/86852/
                                  0
                                  То, что вы назвали «ошибкой», является на самом деле небольшим неудобством. Если вы не разрабатываете эту библиотеку (или тестируете), такое преобразование, которое еще и модифицирует интерфейс функции, ненужно.

                                  И у объекта Exception есть свойство stack.
                                    0
                                    да, подумаешь, не узнать координаты ошибки… мелочи же х) настоящие джедаи видят потоки силы пересекающиеся в проблемных местах!
                                      0
                                      Если вы руками выкидываете эксепшн и интересуетесь стэком вызовов, вам нужно руками его ловить и руками выводить.

                                      try {
                                      throw new Error('hehe');
                                      } catch (e) {
                                      console.debug(e);
                                      }

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

                                      Честно говоря, не помню, когда уже в последний раз видел стэк в JS… Год назад, когда на Dojo что-то делал, вроде видел нет-нет, а потом даж внимания не обращал =)
                                        –2
                                        какого лешего я должен выполнять за браузер его работу?
                                          0
                                          Нет, ну это ж не прям глюк браузера. Это ближе к файербагу же. Кстати, вы бы могли свой класс Error им порекомендовать! Я серьезно
                                            0
                                            не, это похоже на глюк браузера…
                                            у меня нет такого класс, у меня исправляются глюки в стандартном
                                      0
                                      а то я не знаю… habrahabr.ru/blogs/javascript/87098/
                                    +4
                                    В проектах, построенных на node.js, underscore.js может быть очень кстати, т.к. он даёт всё то, что есть в prototype.js и не завязывается на DOM

                                    Ваш К.О.
                                      –1
                                      прототайп как бы тоже не «завязан» на дом
                                        0
                                        Прототайп сильно повязан с DOM. Он и называется прототайпом, потому что расширяет объект prototype стандартных элементов (в т.ч. и DOM).

                                        Это, кстати, сильно затрудняет поддержку кроссбраузерности.
                                          0
                                          он расширяет стандартные объекты и дом в частности. но он не требует наличия дома.
                                      +3
                                      Есть библиотека покруче: osteele.com/sources/javascript/functional/
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                          +1
                                          Да, библиотека крута. Но это какой-то, извиняюсь, функциональный ад.

                                          А по теме поста.

                                          Наконец-то свершилось — нормальный, православный .max(), возвращающий значение массива, а не максимальное значение. Ну очень не хватало!

                                          Очень удобная библиотека для написания встраиваемых скриптов. И без разницы в какое окружение оно встраивается, в Mootools, в Prototype или в JQuery.
                                            0
                                            Это функциональный рай! MAP! REDUCE! EACH!
                                          –1
                                          «вне закона» — это юмор?
                                            0
                                            Всегда было проще написать быстренько свой метод, чем искать и тащить где-то такую библиотеку. Тем более, ничего принципиально сложного в ней нет.
                                            Хотя кому-то несомненно будет полезна.
                                            Кстати, многие функции для работы с массивами отсюда есть и в MooTools

                                              0
                                              И вы каждый раз будете писать свой метод или один раз найдете, научитесь и будете использовать инструмент, код после которого будет легче поддерживать и расширять чем тучи своих простеньких велосипедиков?
                                                0
                                                Подключать на каждую нужную функцию новую библиотеку я точно не буду.
                                              +1
                                              Как и в Prototype, если есть берётся forEach, если нет, используется неправильный аналог.

                                              var a = ['a', 'b'];
                                              a[5] = 'c';
                                              var str = '';
                                              _.each(a, function(item) {
                                                  str += item;
                                              });
                                              alert(str);


                                              В разных браузерах будет разный результат.
                                                +5
                                                В итоге.

                                                each работает по разному в разных браузерах.

                                                        var values = '';
                                                        _.each([1,,2], function(value) {
                                                            values += value;
                                                        });
                                                        alert(values);  // 1undefined2 в IE, 12 в остальных браузерах
                                                


                                                map и filter используют each, поэтому тоже работают по разному, но даже если исправить each, map будет работать неправильно.

                                                indexOf, lastIndexOf тоже работают неправильно.
                                                alert(_.indexOf([1,,undefined], undefined));
                                                Выведет 1 в IE, 2 в остальных браузерах. Хотя в IE в данном конкретном случае должен вывести -1, но это из другой оперы.
                                                +1
                                                Дополнительные функции — это хорошо. А классы в JS — плохо. (да, я не про этот фреймворк, а вообще)
                                                JS тем и прекрасен, что он class-less.
                                                  –2
                                                  Наверное это просто непрофессиональный взгляд на javascript, но я не люблю библиотеки в принципе. Мне кажется, что при постоянном использовании вещей типа jQuery теряешь возможность практиковаться на мелочах. В итоге потом и появляются такие вот полу-шуточные комментарии как на скрине stackoverflow выше.
                                                    0
                                                    А почему она «вне закона»? Я лично из статьи не уловил.

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

                                                    Самое читаемое