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 60-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 modern browsers will use the native implementations of forEach, map, reduce, filter, every, some and indexOf.
A complete Test & Benchmark Suite is included for your perusal.
The unabridged source code is available on GitHub.
Underscore is an open-source component of DocumentCloud.
Development Version (0.5.8) | 22kb, Uncompressed with Comments |
Production Version (0.5.8) | 3kb, Packed and Gzipped |
You can use Underscore in either an object-oriented or a functional style, depending on your preference. The following two lines of code are identical ways to double a list of numbers.
_.map([1, 2, 3], function(n){ return n * 2; }); _([1, 2, 3]).map(function(n){ return n * 2; });
Using the object-oriented style allows you to chain together methods. Calling chain on a wrapped object will cause all future method calls to return wrapped objects as well. When you've finished the computation, use value to retrieve the final value. Here's an example of chaining together a map/flatten/reduce, in order to get the word count of every word in a song.
var lyrics = [ {line : 1, words : "I'm a lumberjack and I'm okay"}, {line : 2, words : "I sleep all night and I work all day"}, {line : 3, words : "He's a lumberjack and he's okay"}, {line : 4, words : "He sleeps all night and he works all day"} ]; _(lyrics).chain() .map(function(line) { return line.words.split(' '); }) .flatten() .reduce({}, function(counts, word) { counts[word] = (counts[word] || 0) + 1; return counts; }).value(); => {lumberjack : 2, all : 4, night : 2 ... }
In addition, the Array prototype's methods are proxied through the chained Underscore object, so you can slip a reverse or a push into your chain, and continue to modify the array.
Collections
each, map,
reduce, reduceRight,
detect, select,
reject, all,
any, include,
invoke, pluck,
max, min,
sortBy, sortedIndex,
toArray, size
Arrays
first, rest, last,
compact, flatten, without, uniq,
intersect, zip, indexOf,
lastIndexOf, range
Functions
bind, bindAll, delay,
defer, wrap, compose
Objects
keys, values,
functions, extend, clone, tap,
isEqual, isEmpty, isElement,
isArray, isArguments, isFunction, isString,
isNumber, isDate, isRegExp
isNaN, isNull,
isUndefined
Utility
noConflict,
identity, breakLoop,
uniqueId, template
Chaining