version 0.2.0 is out, with inject -> reduce, JS standard methodname aliases, a compose(), and a lastIndexOf()

This commit is contained in:
Jeremy Ashkenas
2009-10-28 18:49:50 -04:00
parent 6d52832a73
commit 4a83fcdd26
8 changed files with 294 additions and 158 deletions

View File

@@ -33,9 +33,14 @@
h1, h2, h3, h4, h5, h6 {
margin-top: 40px;
}
b.method_name {
b.header {
font-size: 18px;
}
span.alias {
font-size: 14px;
font-style: italic;
margin-left: 20px;
}
table, tr, td {
margin: 0; padding: 0;
}
@@ -76,7 +81,7 @@
</p>
<p>
Underscore provides 42-odd functions that support both the usual
Underscore provides 44-odd functions that support both the usual
functional suspects: <b>map</b>, <b>select</b>, <b>invoke</b> &mdash;
as well as more specialized helpers: function binding, javascript
templating, deep equality testing, and so on. It delegates to built-in
@@ -102,11 +107,11 @@
<p>
<table>
<tr>
<td><a href="underscore.js">Development Version (0.1.1)</a></td>
<td><a href="underscore.js">Development Version (0.2.0)</a></td>
<td><i>16kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="underscore-min.js">Production Version (0.1.1)</a></td>
<td><a href="underscore-min.js">Production Version (0.2.0)</a></td>
<td><i>4kb, Packed and Gzipped</i></td>
</tr>
</table>
@@ -118,7 +123,7 @@
<b>Collections</b>
<br />
<span class="methods"><a href="#each">each</a>, <a href="#map">map</a>,
<a href="#inject">inject</a>, <a href="#detect">detect</a>, <a href="#select">select</a>, <a href="#reject">reject</a>, <a href="#all">all</a>,
<a href="#reduce">reduce</a>, <a href="#detect">detect</a>, <a href="#select">select</a>, <a href="#reject">reject</a>, <a href="#all">all</a>,
<a href="#any">any</a>, <a href="#include">include</a>, <a href="#invoke">invoke</a>, <a href="#pluck">pluck</a>, <a href="#max">max</a>,
<a href="#min">min</a>, <a href="#sortBy">sortBy</a>, <a href="#sortedIndex">sortedIndex</a>, <a href="#toArray">toArray</a>,
<a href="#size">size</a></span>
@@ -129,14 +134,15 @@
<br />
<span class="methods"><a href="#first">first</a>, <a href="#last">last</a>,
<a href="#compact">compact</a>, <a href="#flatten">flatten</a>, <a href="#without">without</a>, <a href="#uniq">uniq</a>,
<a href="#intersect">intersect</a>, <a href="#zip">zip</a>, <a href="#indexOf">indexOf</a></span>
<a href="#intersect">intersect</a>, <a href="#zip">zip</a>, <a href="#indexOf">indexOf</a></span>,
<a href="#lastIndexOf">lastIndexOf</a></span>
</p>
<p>
<b>Functions</b>
<br />
<span class="methods"><a href="#bind">bind</a>, <a href="#bindAll">bindAll</a>, <a href="#delay">delay</a>,
<a href="#defer">defer</a>, <a href="#wrap">wrap</a></span>
<a href="#defer">defer</a>, <a href="#wrap">wrap</a></span>, <a href="#compose">compose</a></span>
</p>
<p>
@@ -160,7 +166,8 @@
<h2>Collection Functions (Arrays or Objects)</h2>
<p id="each">
<b class="method_name">each</b><code>_.each(list, iterator, [context])</code>
<b class="header">each</b><code>_.each(list, iterator, [context])</code>
<span class="alias">Alias: <b>forEach</b></span>
<br />
Iterates over a <b>list</b> of elements, yielding each in turn to an <b>iterator</b>
function. The <b>iterator</b> is bound to the <b>context</b> object, if one is
@@ -174,7 +181,7 @@ _.each([1, 2, 3], function(num){ alert(num); });
=&gt; alerts each number in turn...</pre>
<p id="map">
<b class="method_name">map</b><code>_.map(list, iterator, [context])</code>
<b class="header">map</b><code>_.map(list, iterator, [context])</code>
<br />
Produces a new array of values by mapping each value in <b>list</b>
through a transformation function (<b>iterator</b>). If the native
@@ -184,21 +191,22 @@ _.each([1, 2, 3], function(num){ alert(num); });
_.map([1, 2, 3], function(num){ return num * 3 });
=&gt; [3, 6, 9]</pre>
<p id="inject">
<b class="method_name">inject</b><code>_.inject(list, memo, iterator, [context])</code>
<p id="reduce">
<b class="header">reduce</b><code>_.reduce(list, memo, iterator, [context])</code>
<span class="alias">Alias: <b>inject</b></span>
<br />
Also known as <b>reduce</b> and <b>foldl</b>, <b>inject</b> reduces a
Also known as <b>inject</b> and <b>foldl</b>, <b>reduce</b> boils down a
<b>list</b> of values into a single value. <b>Memo</b> is the initial state
of the reduction, and each successive step of it should be returned by
<b>iterator</b>.
</p>
<pre>
var sum = _.inject([1, 2, 3], 0, function(memo, num){ return memo + num });
var sum = _.reduce([1, 2, 3], 0, function(memo, num){ return memo + num });
=&gt; 6
</pre>
<p id="detect">
<b class="method_name">detect</b><code>_.detect(list, iterator, [context])</code>
<b class="header">detect</b><code>_.detect(list, iterator, [context])</code>
<br />
Looks through each value in the <b>list</b>, returning the first one that
passes a truth test (<b>iterator</b>). The function returns as
@@ -211,7 +219,8 @@ var even = _.detect([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
</pre>
<p id="select">
<b class="method_name">select</b><code>_.select(list, iterator, [context])</code>
<b class="header">select</b><code>_.select(list, iterator, [context])</code>
<span class="alias">Alias: <b>filter</b></span>
<br />
Looks through each value in the <b>list</b>, returning an array of all
the values that pass a truth test (<b>iterator</b>). Delegates to the
@@ -223,7 +232,7 @@ var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
</pre>
<p id="reject">
<b class="method_name">reject</b><code>_.reject(list, iterator, [context])</code>
<b class="header">reject</b><code>_.reject(list, iterator, [context])</code>
<br />
Returns the values in <b>list</b> without the elements that the truth
test (<b>iterator</b>) passes. The opposite of <b>select</b>.
@@ -234,7 +243,8 @@ var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
</pre>
<p id="all">
<b class="method_name">all</b><code>_.all(list, [iterator], [context])</code>
<b class="header">all</b><code>_.all(list, [iterator], [context])</code>
<span class="alias">Alias: <b>every</b></span>
<br />
Returns <i>true</i> if all of the values in the <b>list</b> pass the <b>iterator</b>
truth test. If an <b>iterator</b> is not provided, the truthy value of
@@ -247,7 +257,8 @@ _.all([true, 1, null, 'yes']);
</pre>
<p id="any">
<b class="method_name">any</b><code>_.any(list, [iterator], [context])</code>
<b class="header">any</b><code>_.any(list, [iterator], [context])</code>
<span class="alias">Alias: <b>some</b></span>
<br />
Returns <i>true</i> if any of the values in the <b>list</b> pass the
<b>iterator</b> truth test. Short-circuits and stops traversing the list
@@ -260,7 +271,7 @@ _.any([null, 0, 'yes', false]);
</pre>
<p id="include">
<b class="method_name">include</b><code>_.include(list, value)</code>
<b class="header">include</b><code>_.include(list, value)</code>
<br />
Returns <i>true</i> if the <b>value</b> is present in the <b>list</b>, using
<i>===</i> to test equality. Uses <b>indexOf</b> internally, if <b>list</b>
@@ -272,7 +283,7 @@ _.include([1, 2, 3], 3);
</pre>
<p id="invoke">
<b class="method_name">invoke</b><code>_.invoke(list, methodName, [*arguments])</code>
<b class="header">invoke</b><code>_.invoke(list, methodName, [*arguments])</code>
<br />
Calls the method named by <b>methodName</b> on each value in the <b>list</b>.
Any extra arguments passed to <b>invoke</b> will be forwarded on to the
@@ -284,7 +295,7 @@ _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
</pre>
<p id="pluck">
<b class="method_name">pluck</b><code>_.pluck(list, propertyName)</code>
<b class="header">pluck</b><code>_.pluck(list, propertyName)</code>
<br />
An optimized version of what is perhaps the most common use-case for
<b>map</b>: returning a list of property values.
@@ -296,7 +307,7 @@ _.pluck(stooges, 'name');
</pre>
<p id="max">
<b class="method_name">max</b><code>_.max(list, [iterator], [context])</code>
<b class="header">max</b><code>_.max(list, [iterator], [context])</code>
<br />
Returns the maximum value in <b>list</b>. If <b>iterator</b> is passed,
it will be used on each value to generate the criterion by which the
@@ -309,7 +320,7 @@ _.max(stooges, function(stooge){ return stooge.age; });
</pre>
<p id="min">
<b class="method_name">min</b><code>_.min(list, [iterator], [context])</code>
<b class="header">min</b><code>_.min(list, [iterator], [context])</code>
<br />
Returns the minimum value in <b>list</b>. If <b>iterator</b> is passed,
it will be used on each value to generate the criterion by which the
@@ -322,7 +333,7 @@ _.min(numbers);
</pre>
<p id="sortBy">
<b class="method_name">sortBy</b><code>_.sortBy(list, iterator, [context])</code>
<b class="header">sortBy</b><code>_.sortBy(list, iterator, [context])</code>
<br />
Returns a sorted <b>list</b>, ranked by the results of running each
value through <b>iterator</b>.
@@ -333,7 +344,7 @@ _.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
</pre>
<p id="sortedIndex">
<b class="method_name">sortedIndex</b><code>_.sortedIndex(list, value, [iterator])</code>
<b class="header">sortedIndex</b><code>_.sortedIndex(list, value, [iterator])</code>
<br />
Uses a binary search to determine the index at which the <b>value</b>
should be inserted into the <b>list</b> in order to maintain the <b>list</b>'s
@@ -346,7 +357,7 @@ _.sortedIndex([10, 20, 30, 40, 50], 35);
</pre>
<p id="toArray">
<b class="method_name">toArray</b><code>_.toArray(list)</code>
<b class="header">toArray</b><code>_.toArray(list)</code>
<br />
Converts the <b>list</b> (anything that can be iterated over), into a
real Array. Useful for transmuting the <b>arguments</b> object.
@@ -357,7 +368,7 @@ _.sortedIndex([10, 20, 30, 40, 50], 35);
</pre>
<p id="size">
<b class="method_name">size</b><code>_.size(list)</code>
<b class="header">size</b><code>_.size(list)</code>
<br />
Return the number of values in the <b>list</b>.
</p>
@@ -369,7 +380,7 @@ _.size({one : 1, two : 2, three : 3});
<h2>Array Functions</h2>
<p id="first">
<b class="method_name">first</b><code>_.first(array)</code>
<b class="header">first</b><code>_.first(array)</code>
<br />
Convenience to return the first element of an <b>array</b> (identical to <tt>array[0]</tt>).
</p>
@@ -379,7 +390,7 @@ _.first([3, 2, 1]);
</pre>
<p id="last">
<b class="method_name">last</b><code>_.last(array)</code>
<b class="header">last</b><code>_.last(array)</code>
<br />
Returns the last element of an <b>array</b>.
</p>
@@ -389,7 +400,7 @@ _.last([3, 2, 1]);
</pre>
<p id="compact">
<b class="method_name">compact</b><code>_.compact(array)</code>
<b class="header">compact</b><code>_.compact(array)</code>
<br />
Returns a copy of the <b>array</b> with all falsy values removed.
In Javascript, <i>false</i>, <i>null</i>, <i>0</i>, <i>""</i>,
@@ -401,7 +412,7 @@ _.compact([0, 1, false, 2, '', 3]);
</pre>
<p id="flatten">
<b class="method_name">flatten</b><code>_.flatten(array)</code>
<b class="header">flatten</b><code>_.flatten(array)</code>
<br />
Flattens a nested <b>array</b> (the nesting can be to any depth).
</p>
@@ -411,7 +422,7 @@ _.flatten([1, [2], [3, [[[4]]]]]);
</pre>
<p id="without">
<b class="method_name">without</b><code>_.without(array, [*values])</code>
<b class="header">without</b><code>_.without(array, [*values])</code>
<br />
Returns a copy of the <b>array</b> with all instances of the <b>values</b>
removed. <i>===</i> is used for the equality test.
@@ -422,7 +433,7 @@ _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
</pre>
<p id="uniq">
<b class="method_name">uniq</b><code>_.uniq(array, [isSorted])</code>
<b class="header">uniq</b><code>_.uniq(array, [isSorted])</code>
<br />
Produces a duplicate-free version of the <b>array</b>, using <i>===</i> to test
object equality. If you know in advance that the <b>array</b> is sorted,
@@ -434,7 +445,7 @@ _.uniq([1, 2, 1, 3, 1, 4]);
</pre>
<p id="intersect">
<b class="method_name">intersect</b><code>_.intersect(*arrays)</code>
<b class="header">intersect</b><code>_.intersect(*arrays)</code>
<br />
Computes the list of values that are the intersection of all the <b>arrays</b>.
Each value in the result is present in each of the <b>arrays</b>.
@@ -445,7 +456,7 @@ _.intersect([1, 2, 3], [101, 2, 1, 10], [2, 1]);
</pre>
<p id="zip">
<b class="method_name">zip</b><code>_.zip(*arrays)</code>
<b class="header">zip</b><code>_.zip(*arrays)</code>
<br />
Merges together the values of each of the <b>arrays</b> with the
values at the corresponding position. Useful when you have separate
@@ -457,7 +468,7 @@ _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
</pre>
<p id="indexOf">
<b class="method_name">indexOf</b><code>_.indexOf(array, value)</code>
<b class="header">indexOf</b><code>_.indexOf(array, value)</code>
<br />
Returns the index at which <b>value</b> can be found in the <b>array</b>,
or <i>-1</i> if value is not present in the <b>array</b>. Uses the native
@@ -466,12 +477,24 @@ _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
<pre>
_.indexOf([1, 2, 3], 2);
=&gt; 1
</pre>
<p id="lastIndexOf">
<b class="header">lastIndexOf</b><code>_.lastIndexOf(array, value)</code>
<br />
Returns the index of the last occurrence of <b>value</b> in the <b>array</b>,
or <i>-1</i> if value is not present. Uses the native <b>lastIndexOf</b>
function if possible.
</p>
<pre>
_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
=&gt; 4
</pre>
<h2>Function (uh, ahem) Functions</h2>
<p id="bind">
<b class="method_name">bind</b><code>_.bind(function, context, [*arguments])</code>
<b class="header">bind</b><code>_.bind(function, context, [*arguments])</code>
<br />
Bind a <b>function</b> to a <b>context</b> object, meaning that whenever
the function is called, the value of <i>this</i> will be the <b>context</b>.
@@ -486,7 +509,7 @@ func();
</pre>
<p id="bindAll">
<b class="method_name">bindAll</b><code>_.bindAll(*methodNames, context)</code>
<b class="header">bindAll</b><code>_.bindAll(*methodNames, context)</code>
<br />
Binds a number of methods on the <b>context</b> object, specified by
<b>methodNames</b>, to be run in the context of that object whenever they
@@ -506,7 +529,7 @@ jQuery('#underscore_button').bind('click', buttonView.onClick);
</pre>
<p id="delay">
<b class="method_name">delay</b><code>_.delay(function, wait, [*arguments])</code>
<b class="header">delay</b><code>_.delay(function, wait, [*arguments])</code>
<br />
Much like <b>setTimeout</b>, invokes <b>function</b> after <b>wait</b>
milliseconds. If you pass the optional <b>arguments</b>, they will be
@@ -519,7 +542,7 @@ _.delay(log, 1000, 'logged later');
</pre>
<p id="defer">
<b class="method_name">defer</b><code>_.defer(function)</code>
<b class="header">defer</b><code>_.defer(function)</code>
<br />
Defers invoking the <b>function</b> until the current call stack has cleared,
similar to using <b>setTimeout</b> with a delay of 0. Useful for performing
@@ -532,7 +555,7 @@ _.defer(function(){ alert('deferred'); });
</pre>
<p id="wrap">
<b class="method_name">wrap</b><code>_.wrap(function, wrapper)</code>
<b class="header">wrap</b><code>_.wrap(function, wrapper)</code>
<br />
Wraps the first <b>function</b> inside of the <b>wrapper</b> function,
passing it as the first argument. This allows the <b>wrapper</b> to
@@ -545,13 +568,29 @@ hello = _.wrap(hello, function(func) {
return "before, " + func("moe") + ", after";
});
hello();
=&gt; before, hello: moe, after
=&gt; 'before, hello: moe, after'
</pre>
<p id="compose">
<b class="header">compose</b><code>_.compose(*functions)</code>
<br />
Returns the composition of a list of <b>functions</b>, where each function
consumes the return value of the function that follows. In math terms,
composing the functions <i>f()</i>, <i>g()</i>, and <i>h()</i> produces
<i>f(g(h()))</i>.
</p>
<pre>
var greet = function(name){ return "hi: " + name; };
var exclaim = function(statement){ return statement + "!"; };
var welcome = _.compose(greet, exclaim);
welcome('moe');
=&gt; 'hi: moe!'
</pre>
<h2>Object Functions</h2>
<p id="keys">
<b class="method_name">keys</b><code>_.keys(object)</code>
<b class="header">keys</b><code>_.keys(object)</code>
<br />
Retrieve all the names of the <b>object</b>'s properties.
</p>
@@ -561,7 +600,7 @@ _.keys({one : 1, two : 2, three : 3});
</pre>
<p id="values">
<b class="method_name">values</b><code>_.values(object)</code>
<b class="header">values</b><code>_.values(object)</code>
<br />
Return all of the values of the <b>object</b>'s properties.
</p>
@@ -571,7 +610,7 @@ _.values({one : 1, two : 2, three : 3});
</pre>
<p id="extend">
<b class="method_name">extend</b><code>_.extend(destination, source)</code>
<b class="header">extend</b><code>_.extend(destination, source)</code>
<br />
Copy all of the properties in the <b>source</b> object over to the
<b>destination</b> object.
@@ -582,7 +621,7 @@ _.extend({name : 'moe'}, {age : 50});
</pre>
<p id="clone">
<b class="method_name">clone</b><code>_.clone(object)</code>
<b class="header">clone</b><code>_.clone(object)</code>
<br />
Create a shallow-copied clone of the <b>object</b>. Any nested objects
or arrays will be copied by reference, not duplicated.
@@ -593,7 +632,7 @@ _.clone({name : 'moe'});
</pre>
<p id="isEqual">
<b class="method_name">isEqual</b><code>_.isEqual(object, other)</code>
<b class="header">isEqual</b><code>_.isEqual(object, other)</code>
<br />
Performs an optimized deep comparison between the two objects, to determine
if they should be considered equal.
@@ -608,7 +647,7 @@ _.isEqual(moe, clone);
</pre>
<p id="isElement">
<b class="method_name">isElement</b><code>_.isElement(object)</code>
<b class="header">isElement</b><code>_.isElement(object)</code>
<br />
Returns <i>true</i> if <b>object</b> is a DOM element.
</p>
@@ -618,7 +657,7 @@ _.isElement(jQuery('body')[0]);
</pre>
<p id="isArray">
<b class="method_name">isArray</b><code>_.isArray(object)</code>
<b class="header">isArray</b><code>_.isArray(object)</code>
<br />
Returns <i>true</i> if <b>object</b> is an Array.
</p>
@@ -630,7 +669,7 @@ _.isArray([1,2,3]);
</pre>
<p id="isFunction">
<b class="method_name">isFunction</b><code>_.isFunction(object)</code>
<b class="header">isFunction</b><code>_.isFunction(object)</code>
<br />
Returns <i>true</i> if <b>object</b> is a Function.
</p>
@@ -640,7 +679,7 @@ _.isFunction(alert);
</pre>
<p id="isUndefined">
<b class="method_name">isUndefined</b><code>_.isUndefined(variable)</code>
<b class="header">isUndefined</b><code>_.isUndefined(variable)</code>
<br />
Returns <i>true</i> if <b>variable</b> is <i>undefined</i>.
</p>
@@ -652,7 +691,7 @@ _.isUndefined(window.missingVariable);
<h2>Utility Functions</h2>
<p id="noConflict">
<b class="method_name">noConflict</b><code>_.noConflict()</code>
<b class="header">noConflict</b><code>_.noConflict()</code>
<br />
Give control of the "_" variable back to its previous owner. Returns
a reference to the <b>Underscore</b> object.
@@ -661,7 +700,7 @@ _.isUndefined(window.missingVariable);
var underscore = _.noConflict();</pre>
<p id="uniqueId">
<b class="method_name">uniqueId</b><code>_.uniqueId([prefix])</code>
<b class="header">uniqueId</b><code>_.uniqueId([prefix])</code>
<br />
Generate a globally-unique id for client-side models or DOM elements
that need one. If <b>prefix</b> is passed, the id will be appended to it.
@@ -672,7 +711,7 @@ _.uniqueId('contact_');
</pre>
<p id="template">
<b class="method_name">template</b><code>_.template(templateString, [context])</code>
<b class="header">template</b><code>_.template(templateString, [context])</code>
<br />
Compiles Javascript templates into functions that can be evaluated
for rendering. Useful for rendering complicated bits of HTML from JSON
@@ -694,6 +733,26 @@ _.template(list, {people : ['moe', 'curly', 'larry']});
=&gt; "&lt;li&gt;moe&lt;/li&gt;&lt;li&gt;curly&lt;/li&gt;&lt;li&gt;larry&lt;/li&gt;"
</pre>
<h2>Change Log</h2>
<p>
<b class="header">0.2.0</b><br />
Added <tt>compose</tt> and <tt>lastIndexOf</tt>, renamed <tt>inject</tt> to
<tt>reduce</tt>, added aliases for <tt>inject</tt>, <tt>filter</tt>,
<tt>every</tt>, <tt>some</tt>, and <tt>forEach</tt>.
</p>
<p>
<b class="header">0.1.1</b><br />
Added <tt>noConflict</tt>, so that the "Underscore" object can be assigned to
other variables.
</p>
<p>
<b class="header">0.1.0</b><br />
Initial release of Underscore.js.
</p>
<p>
<a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;">
<img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" />