Underscore.js

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.

Downloads (Right-click, and use "Save As")

Development Version (0.5.8) 22kb, Uncompressed with Comments
Production Version (0.5.8) 3kb, Packed and Gzipped

Object-Oriented and Functional Styles

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.

Table of Contents

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