JavaScript

индекс
246,38

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. Добавил немного примеров.
+149
15 июля 2010, 04:55
308

комментарии (50)

–30
Anonym #
Не могли бы вы привести пример использования этой библиотеке и объяснить, что же в ней такое есть, чего вам так не хватало при работе с jQuery.
+21
glazs #
JQuery ориентивана на возню с HTML, Underscore же, очевидно из заголовков, ориентирована на упрощение работы с массивами, объектами, функциями, и так далее.
Документацию и примеры можно найти по ссылке.
Anonym, вы, наверно, без глаз.
–12
Anonym #
Да вроде с глазами, просто я, прочитав топик, подумал, что отлично обхожусь без всего этого, вот и решил поинтересоваться.
+17
middle #
Некоторые и без jQuery «отлично обходятся™».
А некоторые даже без Javascript! :)
+5
Anonym #
™ — wapedia.mobi/ru/%D0%A2%D0%9C
Зачем вы поставили этот символ?
+9
middle #
Из хулиганских побуждений, конечно.
+1
sigizmund #
Некоторые и без компьютера отлично обходятся и вообще искренне не понимают красноглазых товарищей ;-)
+2
BlackTheMad #
Эта библиотека нужна для того, чтобы повысить удобство при обработке данных в javascript. В том же jQuery реализована от силы пара функций из приведенных выше. И, по заверениям авторов, их версия работает быстрее.
+2
AntonPoleshchuk #
простой пример
ширина блоков
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
tenshi #
+14
CKOPOBAPKuH #
–2
Tbird #
Шел jQuery через jQuery
Видит jQuery в jQuery jQuery
Сунул jQuery руку в jQuery
jQuery, jQuery, jQuery, jQuery
+6
develop7 #
www.doxdesk.com/img/updates/20091116-so-large.gif
Я просто оставлю это здесь
–1
Stepler #
как раз недавно надо было манипулировать с массивами так же как в примере! автору статьи респект! будем юзать.
–2
bO_oblik #
Эх, засунуть бы все это в jQuery…
0
Xao #
напишите плагин
+8
vittore #
религия не позволяет писать _.блабла() вместо $.блабла()?
+3
tenshi #
религия не позволяет писать _( $( '.user' ) )
+3
seregagl #
Хм, для чего это там? Это отдельный инструмент, ничего не мешает в случае необходимости использовать совместно.
–16
bO_oblik #
Это будет как-то не тру.

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

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

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

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

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

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

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

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

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

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

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

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


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

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, но это из другой оперы.
+2
DmitryBaranovskiy #
Вы послали авторам патч?
+1
lol2Fast4U #
Дополнительные функции — это хорошо. А классы в JS — плохо. (да, я не про этот фреймворк, а вообще)
JS тем и прекрасен, что он class-less.
–2
Aleko #
Наверное это просто непрофессиональный взгляд на javascript, но я не люблю библиотеки в принципе. Мне кажется, что при постоянном использовании вещей типа jQuery теряешь возможность практиковаться на мелочах. В итоге потом и появляются такие вот полу-шуточные комментарии как на скрине stackoverflow выше.

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