mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-29 06:27:49 +00:00
version 0.2.0 is out, with inject -> reduce, JS standard methodname aliases, a compose(), and a lastIndexOf()
This commit is contained in:
167
index.html
167
index.html
@@ -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> —
|
||||
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); });
|
||||
=> 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 });
|
||||
=> [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 });
|
||||
=> 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);
|
||||
=> 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);
|
||||
=> 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();
|
||||
=> before, hello: moe, after
|
||||
=> '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');
|
||||
=> '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']});
|
||||
=> "<li>moe</li><li>curly</li><li>larry</li>"
|
||||
</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" />
|
||||
|
||||
12
package.json
Normal file
12
package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
// ServerJS package specification.
|
||||
{
|
||||
"name": "underscore",
|
||||
"description": "Functional programming aid for Javascript. Works well with jQuery.",
|
||||
"url": "http://documentcloud.github.com/underscore/",
|
||||
"keywords": ["util", "functional", "server", "client", "browser"],
|
||||
"author": "Jeremy Ashkenas <jeremy@documentcloud.org>",
|
||||
"maintainer": "Kris Kowal <kris.kowal@cixar.com>",
|
||||
"contributors": [],
|
||||
"dependencies": [],
|
||||
"lib", "."
|
||||
}
|
||||
@@ -49,4 +49,11 @@ $(document).ready(function() {
|
||||
equals(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
||||
});
|
||||
|
||||
test("arrays: lastIndexOf", function() {
|
||||
var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||
numbers.lastIndexOf = null;
|
||||
equals(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||
equals(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -14,6 +14,10 @@ $(document).ready(function() {
|
||||
var answers = [];
|
||||
_.each([1, 2, 3], function(num) { answers.push(num * this.multiplier);}, {multiplier : 5});
|
||||
equals(answers.join(', '), '5, 10, 15', 'context object property accessed');
|
||||
|
||||
answers = [];
|
||||
_.forEach([1, 2, 3], function(num){ answers.push(num); });
|
||||
equals(answers.join(', '), '1, 2, 3', 'aliased as "forEach"');
|
||||
});
|
||||
|
||||
test('collections: map', function() {
|
||||
@@ -24,9 +28,12 @@ $(document).ready(function() {
|
||||
equals(tripled.join(', '), '3, 6, 9', 'tripled numbers with context');
|
||||
});
|
||||
|
||||
test('collections: inject', function() {
|
||||
var sum = _.inject([1,2,3], 0, function(sum, num){ return sum + num; });
|
||||
test('collections: reduce', function() {
|
||||
var sum = _.reduce([1, 2, 3], 0, function(sum, num){ return sum + num; });
|
||||
equals(sum, 6, 'can sum up an array');
|
||||
|
||||
sum = _.inject([1, 2, 3], 0, function(sum, num){ return sum + num; });
|
||||
equals(sum, 6, 'aliased as "inject"');
|
||||
});
|
||||
|
||||
test('collections: detect', function() {
|
||||
@@ -37,6 +44,9 @@ $(document).ready(function() {
|
||||
test('collections: select', function() {
|
||||
var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
||||
equals(evens.join(', '), '2, 4, 6', 'selected each even number');
|
||||
|
||||
evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
||||
equals(evens.join(', '), '2, 4, 6', 'aliased as "filter"');
|
||||
});
|
||||
|
||||
test('collections: reject', function() {
|
||||
@@ -50,6 +60,7 @@ $(document).ready(function() {
|
||||
ok(!_.all([true, false, true]), 'one false value');
|
||||
ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers');
|
||||
ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number');
|
||||
ok(_.every([true, true, true]), 'aliased as "every"');
|
||||
});
|
||||
|
||||
test('collections: any', function() {
|
||||
@@ -58,6 +69,7 @@ $(document).ready(function() {
|
||||
ok(_.any([false, false, true]), 'one true value');
|
||||
ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers');
|
||||
ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number');
|
||||
ok(_.some([false, false, true]), 'aliased as "some"');
|
||||
});
|
||||
|
||||
test('collections: include', function() {
|
||||
|
||||
@@ -48,4 +48,14 @@ $(document).ready(function() {
|
||||
equals(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
|
||||
});
|
||||
|
||||
test("functions: compose", function() {
|
||||
var greet = function(name){ return "hi: " + name; };
|
||||
var exclaim = function(sentence){ return sentence + '!'; };
|
||||
var composed = _.compose(exclaim, greet);
|
||||
equals(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
|
||||
|
||||
composed = _.compose(greet, exclaim);
|
||||
equals(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -5,6 +5,8 @@ $(document).ready(function() {
|
||||
test("utility: noConflict", function() {
|
||||
var underscore = _.noConflict();
|
||||
ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state.");
|
||||
var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]);
|
||||
equals(intersection.join(', '), '1, 2', 'but the intersection function still works');
|
||||
window._ = underscore;
|
||||
});
|
||||
|
||||
|
||||
2
underscore-min.js
vendored
2
underscore-min.js
vendored
File diff suppressed because one or more lines are too long
232
underscore.js
232
underscore.js
@@ -5,17 +5,22 @@
|
||||
// Oliver Steele's Functional, And John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore/
|
||||
window.Underscore = {
|
||||
|
||||
VERSION : '0.1.1',
|
||||
(function() {
|
||||
|
||||
PREVIOUS_UNDERSCORE : window._,
|
||||
var root = (typeof window != 'undefined') ? window : exports;
|
||||
|
||||
var previousUnderscore = root._;
|
||||
|
||||
var _ = root._ = {};
|
||||
|
||||
_.VERSION = '0.2.0';
|
||||
|
||||
/*------------------------ Collection Functions: ---------------------------*/
|
||||
|
||||
// The cornerstone, an each implementation.
|
||||
// Handles objects implementing forEach, each, arrays, and raw objects.
|
||||
each : function(obj, iterator, context) {
|
||||
_.each = function(obj, iterator, context) {
|
||||
var index = 0;
|
||||
try {
|
||||
if (obj.forEach) {
|
||||
@@ -37,30 +42,30 @@ window.Underscore = {
|
||||
if (e != '__break__') throw e;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
};
|
||||
|
||||
// Return the results of applying the iterator to each element. Use Javascript
|
||||
// 1.6's version of map, if possible.
|
||||
map : function(obj, iterator, context) {
|
||||
_.map = function(obj, iterator, context) {
|
||||
if (obj && obj.map) return obj.map(iterator, context);
|
||||
var results = [];
|
||||
_.each(obj, function(value, index) {
|
||||
results.push(iterator.call(context, value, index));
|
||||
});
|
||||
return results;
|
||||
},
|
||||
};
|
||||
|
||||
// Inject builds up a single result from a list of values. Also known as
|
||||
// reduce, or foldl.
|
||||
inject : function(obj, memo, iterator, context) {
|
||||
// Reduce builds up a single result from a list of values. Also known as
|
||||
// inject, or foldl.
|
||||
_.reduce = function(obj, memo, iterator, context) {
|
||||
_.each(obj, function(value, index) {
|
||||
memo = iterator.call(context, memo, value, index);
|
||||
});
|
||||
return memo;
|
||||
},
|
||||
};
|
||||
|
||||
// Return the first value which passes a truth test.
|
||||
detect : function(obj, iterator, context) {
|
||||
_.detect = function(obj, iterator, context) {
|
||||
var result;
|
||||
_.each(obj, function(value, index) {
|
||||
if (iterator.call(context, value, index)) {
|
||||
@@ -69,31 +74,31 @@ window.Underscore = {
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
// Return all the elements that pass a truth test. Use Javascript 1.6's
|
||||
// filter(), if it exists.
|
||||
select : function(obj, iterator, context) {
|
||||
_.select = function(obj, iterator, context) {
|
||||
if (obj.filter) return obj.filter(iterator, context);
|
||||
var results = [];
|
||||
_.each(obj, function(value, index) {
|
||||
if (iterator.call(context, value, index)) results.push(value);
|
||||
});
|
||||
return results;
|
||||
},
|
||||
};
|
||||
|
||||
// Return all the elements for which a truth test fails.
|
||||
reject : function(obj, iterator, context) {
|
||||
_.reject = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
_.each(obj, function(value, index) {
|
||||
if (!iterator.call(context, value, index)) results.push(value);
|
||||
});
|
||||
return results;
|
||||
},
|
||||
};
|
||||
|
||||
// Determine whether all of the elements match a truth test. Delegate to
|
||||
// Javascript 1.6's every(), if it is present.
|
||||
all : function(obj, iterator, context) {
|
||||
_.all = function(obj, iterator, context) {
|
||||
iterator = iterator || function(v){ return v; };
|
||||
if (obj.every) return obj.every(iterator, context);
|
||||
var result = true;
|
||||
@@ -102,11 +107,11 @@ window.Underscore = {
|
||||
if (!result) throw '__break__';
|
||||
});
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
// Determine if at least one element in the object matches a truth test. Use
|
||||
// Javascript 1.6's some(), if it exists.
|
||||
any : function(obj, iterator, context) {
|
||||
_.any = function(obj, iterator, context) {
|
||||
iterator = iterator || function(v) { return v; };
|
||||
if (obj.some) return obj.some(iterator, context);
|
||||
var result = false;
|
||||
@@ -114,11 +119,11 @@ window.Underscore = {
|
||||
if (result = !!iterator.call(context, value, index)) throw '__break__';
|
||||
});
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
// Determine if a given value is included in the array or object,
|
||||
// based on '==='.
|
||||
include : function(obj, target) {
|
||||
_.include = function(obj, target) {
|
||||
if (_.isArray(obj)) return _.indexOf(obj, target) != -1;
|
||||
var found = false;
|
||||
_.each(obj, function(pair) {
|
||||
@@ -128,25 +133,25 @@ window.Underscore = {
|
||||
}
|
||||
});
|
||||
return found;
|
||||
},
|
||||
};
|
||||
|
||||
// Invoke a method with arguments on every item in a collection.
|
||||
invoke : function(obj, method) {
|
||||
_.invoke = function(obj, method) {
|
||||
var args = _.toArray(arguments).slice(2);
|
||||
return _.map(obj, function(value) {
|
||||
return (method ? value[method] : value).apply(value, args);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Optimized version of a common use case of map: fetching a property.
|
||||
pluck : function(obj, key) {
|
||||
_.pluck = function(obj, key) {
|
||||
var results = [];
|
||||
_.each(obj, function(value){ results.push(value[key]); });
|
||||
return results;
|
||||
},
|
||||
};
|
||||
|
||||
// Return the maximum item or (item-based computation).
|
||||
max : function(obj, iterator, context) {
|
||||
_.max = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||
var result;
|
||||
_.each(obj, function(value, index) {
|
||||
@@ -154,10 +159,10 @@ window.Underscore = {
|
||||
if (result == null || computed >= result.computed) result = {value : value, computed : computed};
|
||||
});
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
|
||||
// Return the minimum element (or element-based computation).
|
||||
min : function(obj, iterator, context) {
|
||||
_.min = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||
var result;
|
||||
_.each(obj, function(value, index) {
|
||||
@@ -165,10 +170,10 @@ window.Underscore = {
|
||||
if (result == null || computed < result.computed) result = {value : value, computed : computed};
|
||||
});
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
|
||||
// Sort the object's values by a criteria produced by an iterator.
|
||||
sortBy : function(obj, iterator, context) {
|
||||
_.sortBy = function(obj, iterator, context) {
|
||||
return _.pluck(_.map(obj, function(value, index) {
|
||||
return {
|
||||
value : value,
|
||||
@@ -178,11 +183,11 @@ window.Underscore = {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}), 'value');
|
||||
},
|
||||
};
|
||||
|
||||
// Use a comparator function to figure out at what index an object should
|
||||
// be inserted so as to maintain order. Uses binary search.
|
||||
sortedIndex : function(array, obj, iterator) {
|
||||
_.sortedIndex = function(array, obj, iterator) {
|
||||
iterator = iterator || function(val) { return val; };
|
||||
var low = 0, high = array.length;
|
||||
while (low < high) {
|
||||
@@ -190,163 +195,182 @@ window.Underscore = {
|
||||
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||
}
|
||||
return low;
|
||||
},
|
||||
};
|
||||
|
||||
// Convert anything iterable into a real, live array.
|
||||
toArray : function(iterable) {
|
||||
_.toArray = function(iterable) {
|
||||
if (!iterable) return [];
|
||||
if (_.isArray(iterable)) return iterable;
|
||||
return _.map(iterable, function(val){ return val; });
|
||||
},
|
||||
};
|
||||
|
||||
// Return the number of elements in an object.
|
||||
size : function(obj) {
|
||||
_.size = function(obj) {
|
||||
return _.toArray(obj).length;
|
||||
},
|
||||
};
|
||||
|
||||
/*-------------------------- Array Functions: ------------------------------*/
|
||||
|
||||
// Get the first element of an array.
|
||||
first : function(array) {
|
||||
_.first = function(array) {
|
||||
return array[0];
|
||||
},
|
||||
};
|
||||
|
||||
// Get the last element of an array.
|
||||
last : function(array) {
|
||||
_.last = function(array) {
|
||||
return array[array.length - 1];
|
||||
},
|
||||
};
|
||||
|
||||
// Trim out all falsy values from an array.
|
||||
compact : function(array) {
|
||||
_.compact = function(array) {
|
||||
return _.select(array, function(value){ return !!value; });
|
||||
},
|
||||
};
|
||||
|
||||
// Return a completely flattened version of an array.
|
||||
flatten : function(array) {
|
||||
return _.inject(array, [], function(memo, value) {
|
||||
_.flatten = function(array) {
|
||||
return _.reduce(array, [], function(memo, value) {
|
||||
if (_.isArray(value)) return memo.concat(_.flatten(value));
|
||||
memo.push(value);
|
||||
return memo;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Return a version of the array that does not contain the specified value(s).
|
||||
without : function(array) {
|
||||
_.without = function(array) {
|
||||
var values = array.slice.call(arguments, 0);
|
||||
return _.select(array, function(value){ return !_.include(values, value); });
|
||||
},
|
||||
};
|
||||
|
||||
// Produce a duplicate-free version of the array. If the array has already
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
uniq : function(array, isSorted) {
|
||||
return _.inject(array, [], function(memo, el, i) {
|
||||
_.uniq = function(array, isSorted) {
|
||||
return _.reduce(array, [], function(memo, el, i) {
|
||||
if (0 == i || (isSorted ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
|
||||
return memo;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Produce an array that contains every item shared between all the
|
||||
// passed-in arrays.
|
||||
intersect : function(array) {
|
||||
_.intersect = function(array) {
|
||||
var rest = _.toArray(arguments).slice(1);
|
||||
return _.select(_.uniq(array), function(item) {
|
||||
return _.all(rest, function(other) {
|
||||
return _.indexOf(other, item) >= 0;
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Zip together multiple lists into a single array -- elements that share
|
||||
// an index go together.
|
||||
zip : function() {
|
||||
_.zip = function() {
|
||||
var args = _.toArray(arguments);
|
||||
var length = _.max(_.pluck(args, 'length'));
|
||||
var results = new Array(length);
|
||||
for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
|
||||
return results;
|
||||
},
|
||||
};
|
||||
|
||||
// If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
||||
// we need this function. Return the position of the first occurence of an
|
||||
// item in an array, or -1 if the item is not included in the array.
|
||||
indexOf : function(array, item) {
|
||||
_.indexOf = function(array, item) {
|
||||
if (array.indexOf) return array.indexOf(item);
|
||||
var length = array.length;
|
||||
for (i=0; i<length; i++) if (array[i] === item) return i;
|
||||
for (i=0; i<array.length; i++) if (array[i] === item) return i;
|
||||
return -1;
|
||||
},
|
||||
};
|
||||
|
||||
// Provide Javascript 1.6's lastIndexOf, delegating to the native function,
|
||||
// if possible.
|
||||
_.lastIndexOf = function(array, item) {
|
||||
if (array.lastIndexOf) return array.lastIndexOf(item);
|
||||
for (i=array.length - 1; i>=0; i--) if (array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
/* ----------------------- Function Functions: -----------------------------*/
|
||||
|
||||
// Create a function bound to a given object (assigning 'this', and arguments,
|
||||
// optionally). Binding with arguments is also known as 'curry'.
|
||||
bind : function(func, context) {
|
||||
_.bind = function(func, context) {
|
||||
if (!context) return func;
|
||||
var args = _.toArray(arguments).slice(2);
|
||||
return function() {
|
||||
var a = args.concat(_.toArray(arguments));
|
||||
return func.apply(context, a);
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||
// all callbacks defined on an object belong to it.
|
||||
bindAll : function() {
|
||||
_.bindAll = function() {
|
||||
var args = _.toArray(arguments);
|
||||
var context = args.pop();
|
||||
_.each(args, function(methodName) {
|
||||
context[methodName] = _.bind(context[methodName], context);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Delays a function for the given number of milliseconds, and then calls
|
||||
// it with the arguments supplied.
|
||||
delay : function(func, wait) {
|
||||
_.delay = function(func, wait) {
|
||||
var args = _.toArray(arguments).slice(2);
|
||||
return window.setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||
},
|
||||
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||
};
|
||||
|
||||
// Defers a function, scheduling it to run after the current call stack has
|
||||
// cleared.
|
||||
defer : function(func) {
|
||||
_.defer = function(func) {
|
||||
return _.delay.apply(_, [func, 1].concat(_.toArray(arguments).slice(1)));
|
||||
},
|
||||
};
|
||||
|
||||
// Returns the first function passed as an argument to the second,
|
||||
// allowing you to adjust arguments, run code before and after, and
|
||||
// conditionally execute the original function.
|
||||
wrap : function(func, wrapper) {
|
||||
_.wrap = function(func, wrapper) {
|
||||
return function() {
|
||||
var args = [func].concat(_.toArray(arguments));
|
||||
return wrapper.apply(wrapper, args);
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// Returns a function that is the composition of a list of functions, each
|
||||
// consuming the return value of the function that follows.
|
||||
_.compose = function() {
|
||||
var funcs = _.toArray(arguments);
|
||||
return function() {
|
||||
for (var i=funcs.length-1; i >= 0; i--) {
|
||||
arguments = [funcs[i].apply(this, arguments)];
|
||||
}
|
||||
return arguments[0];
|
||||
};
|
||||
};
|
||||
|
||||
/* ------------------------- Object Functions: ---------------------------- */
|
||||
|
||||
// Retrieve the names of an object's properties.
|
||||
keys : function(obj) {
|
||||
_.keys = function(obj) {
|
||||
return _.pluck(obj, 'key');
|
||||
},
|
||||
};
|
||||
|
||||
// Retrieve the values of an object's properties.
|
||||
values : function(obj) {
|
||||
_.values = function(obj) {
|
||||
return _.pluck(obj, 'value');
|
||||
},
|
||||
};
|
||||
|
||||
// Extend a given object with all of the properties in a source object.
|
||||
extend : function(destination, source) {
|
||||
_.extend = function(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
},
|
||||
};
|
||||
|
||||
// Create a (shallow-cloned) duplicate of an object.
|
||||
clone : function(obj) {
|
||||
_.clone = function(obj) {
|
||||
return _.extend({}, obj);
|
||||
},
|
||||
};
|
||||
|
||||
// Perform a deep comparison to check if two objects are equal.
|
||||
isEqual : function(a, b) {
|
||||
_.isEqual = function(a, b) {
|
||||
// Check object identity.
|
||||
if (a === b) return true;
|
||||
// Different types?
|
||||
@@ -365,47 +389,47 @@ window.Underscore = {
|
||||
// Recursive comparison of contents.
|
||||
for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
// Is a given value a DOM element?
|
||||
isElement : function(obj) {
|
||||
_.isElement = function(obj) {
|
||||
return !!(obj && obj.nodeType == 1);
|
||||
},
|
||||
};
|
||||
|
||||
// Is a given value a real Array?
|
||||
isArray : function(obj) {
|
||||
_.isArray = function(obj) {
|
||||
return Object.prototype.toString.call(obj) == '[object Array]';
|
||||
},
|
||||
};
|
||||
|
||||
// Is a given value a Function?
|
||||
isFunction : function(obj) {
|
||||
_.isFunction = function(obj) {
|
||||
return typeof obj == 'function';
|
||||
},
|
||||
};
|
||||
|
||||
// Is a given variable undefined?
|
||||
isUndefined : function(obj) {
|
||||
_.isUndefined = function(obj) {
|
||||
return typeof obj == 'undefined';
|
||||
},
|
||||
};
|
||||
|
||||
/* -------------------------- Utility Functions: -------------------------- */
|
||||
|
||||
// Run Underscore.js in noConflict mode, returning the '_' variable to its
|
||||
// previous owner. Returns a reference to the Underscore object.
|
||||
noConflict : function() {
|
||||
window._ = Underscore.PREVIOUS_UNDERSCORE;
|
||||
_.noConflict = function() {
|
||||
root._ = previousUnderscore;
|
||||
return this;
|
||||
},
|
||||
};
|
||||
|
||||
// Generate a unique integer id (unique within the entire client session).
|
||||
// Useful for temporary DOM ids.
|
||||
uniqueId : function(prefix) {
|
||||
_.uniqueId = function(prefix) {
|
||||
var id = this._idCounter = (this._idCounter || 0) + 1;
|
||||
return prefix ? prefix + id : id;
|
||||
},
|
||||
};
|
||||
|
||||
// Javascript templating a-la ERB, pilfered from John Resig's
|
||||
// "Secrets of the Javascript Ninja", page 83.
|
||||
template : function(str, data) {
|
||||
_.template = function(str, data) {
|
||||
var fn = new Function('obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj){p.push(\'' +
|
||||
@@ -419,8 +443,18 @@ window.Underscore = {
|
||||
.split("\r").join("\\'")
|
||||
+ "');}return p.join('');");
|
||||
return data ? fn(data) : fn;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
window._ = Underscore;
|
||||
/*------------------------------- Aliases ----------------------------------*/
|
||||
|
||||
_.forEach = _.each;
|
||||
_.inject = _.reduce;
|
||||
_.filter = _.select;
|
||||
_.every = _.all;
|
||||
_.some = _.any;
|
||||
|
||||
/*------------------------- Export for ServerJS ----------------------------*/
|
||||
|
||||
if (!_.isUndefined(exports)) exports = _;
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user