Underscore is a utility-belt library for Javascript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in Javascript objects. It's the tie to go along with jQuery's tux.
Underscore provides 43-odd functions that support both the usual functional suspects: map, select, invoke — as well as more specialized helpers: function binding, javascript templating, deep equality testing, and so on. It delegates to built-in functions, if present, so Javascript 1.6 compliant browsers will use the native implementations of forEach, map, filter, every, some and indexOf.
Underscore includes a complete Test & Benchmark Suite for your perusal.
Collections
each, map,
inject, detect, select, reject, all,
any, include, invoke, pluck, max,
min, sortBy, sortedIndex, toArray,
size
Arrays
first, last,
compact, flatten, without, uniq,
intersect, zip, indexOf
Objects
keys, values,
extend, clone, isEqual, isElement,
isArray, isFunction, isUndefined, toString
Functions
bind, bindAll, delay,
defer, wrap
each_.each(list, iterator, [context])
Iterates over a list of elements, yielding each in turn to an iterator
function. The iterator is bound to the context object, if one is
passed. If list is a Javascript object, a pair with key
and value properties will be yielded. Delegates to the native
forEach method if it exists.
_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...
map_.map(list, iterator, [context])
Produces a new array of values by mapping each value in list
through a transformation function (iterator). If the native
map method exists, it will be used instead.
_.map([1, 2, 3], function(num){ return num * 3 });
=> [3, 6, 9]
inject_.inject(list, memo, iterator, [context])
Also known as reduce and foldl, inject reduces a
list of values into a single value. Memo is the initial state
of the reduction, and each successive step of it should be returned by
iterator.
var sum = _.inject([1, 2, 3], 0, function(memo, num){ return memo + num });
=> 6
detect_.detect(list, iterator, [context])
Looks through each value in the list, returning the first one that
passes a truth test (iterator). The function returns as
soon as it finds the true element, and doesn't continue to traverse
the list.
var even = _.detect([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> 2
select_.select(list, iterator, [context])
Looks through each value in the list, returning an array of all
the values that pass a truth test (iterator). Delegates to the
native filter method, if it exists.
var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> [2, 4, 6]
reject_.reject(list, iterator, [context])
Returns the values in list without the elements that the truth
test (iterator) passes. The opposite of select.
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> [1, 3, 5]
all_.all(list, [iterator], [context])
Returns true if all of the values in the list pass the iterator
truth test. If an iterator is not provided, the truthy value of
the element will be used instead. Delegates to the native method every, if
present.
_.all([true, 1, null, 'yes']); => false
any_.any(list, iterator, [context])
Returns true if any of the values in the list pass the
iterator truth test. Short-circuits and stops traversing the list
if a true element is found. Delegates to the native method some,
if present.
_.any([null, 0, 'yes', false]); => true
include_.include(list, value)
Returns true if the value is present in the list, using
== to test equality. Uses indexOf internally, if list
is an Array.
_.include([1, 2, 3], 3); => true
invoke_.invoke(list, methodName)
Calls the method named by methodName on each value in the list.
Any extra arguments passed to invoke will be forwarded on to the
method invocation.
_.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); => [[1, 5, 7], [1, 2, 3]]
pluck_.pluck(list, propertyName)
An optimized version of what is perhaps the most common use-case for
map: returning a list of property values.
var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
_.pluck(stooges, 'name');
=> ["moe", "larry", "curly"]
max_.max(list, [iterator], [context])
Returns the maximum value in list. If iterator is passed,
it will be used on each value to generate the criterion by which the
value is ranked.
var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
_.max(stooges, function(stooge){ return stooge.age; });
=> {name : 'curly', age : 60};
min_.min(list, [iterator], [context])
Returns the minimum value in list. If iterator is passed,
it will be used on each value to generate the criterion by which the
value is ranked.
var numbers = [10, 5, 100, 2, 1000]; _.min(numbers); => 2
sortBy_.sortBy(list, iterator, [context])
Returns a sorted list, ranked by the results of running each
value through iterator.
_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
=> [5, 4, 6, 3, 1, 2]
sortedIndex_.sortedIndex(list, value, [iterator])
Uses a binary search to determine the index at which the value
should be inserted into the list in order to maintain the list's
sorted order. If an iterator is passed, it will be used to compute
the sort ranking of each value.
_.sortedIndex([10, 20, 30, 40, 50], 35); => 3
toArray_.(list, iterator, [context])
size_.(list, iterator, [context])