mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-31 23:37:49 +00:00
0.4.0 is out, with OOP-style and chaining
This commit is contained in:
66
index.html
66
index.html
@@ -107,16 +107,55 @@
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="underscore.js">Development Version (0.3.3)</a></td>
|
||||
<td><a href="underscore.js">Development Version (0.4.0)</a></td>
|
||||
<td><i>16kb, Uncompressed with Comments</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="underscore-min.js">Production Version (0.3.3)</a></td>
|
||||
<td><a href="underscore-min.js">Production Version (0.4.0)</a></td>
|
||||
<td><i>2kb, Packed and Gzipped</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<h2>Object-Oriented and Functional Styles</h2>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
_.map([1, 2, 3], function(n){ return n * 2; });
|
||||
_([1, 2, 3]).map(function(n){ return n * 2; });</pre>
|
||||
|
||||
<p>
|
||||
Using the object-oriented style allows you to chain together methods. Calling
|
||||
<tt>chain</tt> on a wrapped object will cause all future method calls to
|
||||
return wrapped objects as well. When you've finished the computation,
|
||||
use <tt>get</tt> to retrieve the final value. Here's an example of chaining
|
||||
together a <b>map/flatten/reduce</b>, in order to get the word count of
|
||||
every word in a song.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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;
|
||||
}).get();
|
||||
|
||||
=> returns a hash containing the word counts...</pre>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
<p>
|
||||
@@ -742,6 +781,17 @@ moe === _.identity(moe);
|
||||
<pre>
|
||||
_.uniqueId('contact_');
|
||||
=> 'contact_104'
|
||||
</pre>
|
||||
|
||||
<p id="functions">
|
||||
<b class="header">functions</b><code>_.functions([prefix])</code>
|
||||
<span class="alias">Alias: <b>methods</b></span>
|
||||
<br />
|
||||
Returns a sorted list of the name of every function in Underscore.
|
||||
</p>
|
||||
<pre>
|
||||
_.functions();
|
||||
=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
|
||||
</pre>
|
||||
|
||||
<p id="template">
|
||||
@@ -769,6 +819,16 @@ _.template(list, {people : ['moe', 'curly', 'larry']});
|
||||
|
||||
<h2>Change Log</h2>
|
||||
|
||||
<p>
|
||||
<b class="header">0.4.0</b><br />
|
||||
All Underscore functions can now be called in an object-oriented style,
|
||||
like so: <tt>_([1, 2, 3]).map(...);</tt>. Original patch provided by
|
||||
<a href="http://macournoyer.com/">Marc-André Cournoyer</a>.
|
||||
Wrapped objects can be chained through multiple
|
||||
method invocations. A <a href="#functions"><tt>functions</tt></a> method
|
||||
was added, providing a sorted list of all the functions in Underscore.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header">0.3.3</b><br />
|
||||
Added the JavaScript 1.8 function <tt>reduceRight</tt>. Aliased it
|
||||
@@ -787,7 +847,7 @@ _.template(list, {people : ['moe', 'curly', 'larry']});
|
||||
All iterators are now passed in the original collection as their third
|
||||
argument, the same as JavaScript 1.6's <b>forEach</b>. Iterating over
|
||||
objects is now called with <tt>(value, key, collection)</tt>, for details
|
||||
see <a href="#each">_.each</a>.
|
||||
see <a href="#each"><tt>_.each</tt></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
35
test/chaining.js
Normal file
35
test/chaining.js
Normal file
@@ -0,0 +1,35 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Underscore chaining.");
|
||||
|
||||
test("chaining: map/flatten/reduce", function() {
|
||||
var lyrics = [
|
||||
"I'm a lumberjack and I'm okay",
|
||||
"I sleep all night and I work all day",
|
||||
"He's a lumberjack and he's okay",
|
||||
"He sleeps all night and he works all day"
|
||||
];
|
||||
var counts = _(lyrics).chain()
|
||||
.map(function(line) { return line.split(''); })
|
||||
.flatten()
|
||||
.reduce({}, function(hash, l) {
|
||||
hash[l] = hash[l] || 0;
|
||||
hash[l]++;
|
||||
return hash;
|
||||
}).get();
|
||||
ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');
|
||||
});
|
||||
|
||||
test("chaining: select/reject/sortBy", function() {
|
||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||
numbers = _(numbers).chain().select(function(n) {
|
||||
return n % 2 == 0;
|
||||
}).reject(function(n) {
|
||||
return n % 4 == 0;
|
||||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).get();
|
||||
equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
||||
});
|
||||
|
||||
});
|
||||
@@ -12,6 +12,7 @@
|
||||
<script type="text/javascript" src="functions.js"></script>
|
||||
<script type="text/javascript" src="objects.js"></script>
|
||||
<script type="text/javascript" src="utility.js"></script>
|
||||
<script type="text/javascript" src="chaining.js"></script>
|
||||
<script type="text/javascript" src="speed.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -21,6 +21,18 @@ $(document).ready(function() {
|
||||
equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
||||
});
|
||||
|
||||
test("utility: functions", function() {
|
||||
var expected = ["all", "any", "bind", "bindAll", "clone", "compact", "compose",
|
||||
"defer", "delay", "detect", "each", "every", "extend", "filter", "first",
|
||||
"flatten", "foldl", "foldr", "forEach", "functions", "identity", "include",
|
||||
"indexOf", "inject", "intersect", "invoke", "isArray", "isElement", "isEqual",
|
||||
"isFunction", "isUndefined", "keys", "last", "lastIndexOf", "map", "max",
|
||||
"methods", "min", "pluck", "reduce", "reduceRight", "reject", "select",
|
||||
"size", "some", "sortBy", "sortedIndex", "template", "toArray", "uniq",
|
||||
"uniqueId", "values", "without", "wrap", "zip"];
|
||||
ok(_(expected).isEqual(_.methods()), 'provides a sorted list of functions');
|
||||
});
|
||||
|
||||
test("utility: template", function() {
|
||||
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
||||
var result = basicTemplate({thing : 'This'});
|
||||
|
||||
2
underscore-min.js
vendored
2
underscore-min.js
vendored
File diff suppressed because one or more lines are too long
@@ -18,8 +18,8 @@
|
||||
|
||||
// If Underscore is called as a function, it returns a wrapped object that
|
||||
// can be used OO-style. This wrapper holds altered versions of all the
|
||||
// underscore functions.
|
||||
var wrapper = function(obj) { this.wrapped = obj; };
|
||||
// underscore functions. Wrapped objects may be chained.
|
||||
var wrapper = function(obj) { this._wrapped = obj; };
|
||||
|
||||
// Create a safe reference to the Underscore object for reference below.
|
||||
var _ = root._ = function(obj) { return new wrapper(obj); };
|
||||
@@ -28,7 +28,7 @@
|
||||
if (typeof exports !== 'undefined') _ = exports;
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '0.3.3';
|
||||
_.VERSION = '0.4.0';
|
||||
|
||||
/*------------------------ Collection Functions: ---------------------------*/
|
||||
|
||||
@@ -447,8 +447,9 @@
|
||||
|
||||
// Generate a unique integer id (unique within the entire client session).
|
||||
// Useful for temporary DOM ids.
|
||||
var idCounter = 0;
|
||||
_.uniqueId = function(prefix) {
|
||||
var id = this._idCounter = (this._idCounter || 0) + 1;
|
||||
var id = idCounter++;
|
||||
return prefix ? prefix + id : id;
|
||||
};
|
||||
|
||||
@@ -456,7 +457,7 @@
|
||||
_.functions = function() {
|
||||
var functions = [];
|
||||
for (var key in _) if (Object.prototype.hasOwnProperty.call(_, key)) functions.push(key);
|
||||
return _.without(functions, 'VERSION', 'prototype', 'noConflict');
|
||||
return _.without(functions, 'VERSION', 'prototype', 'noConflict').sort();
|
||||
};
|
||||
|
||||
// JavaScript templating a-la ERB, pilfered from John Resig's
|
||||
@@ -487,13 +488,26 @@
|
||||
_.some = _.any;
|
||||
_.methods = _.functions;
|
||||
|
||||
/*------------------- Add all Functions to the Wrapper: --------------------*/
|
||||
|
||||
/*------------------------ Setup the OOP Wrapper: --------------------------*/
|
||||
|
||||
// Add all of the Underscore functions to the wrapper object.
|
||||
_.each(_.functions(), function(name) {
|
||||
wrapper.prototype[name] = function() {
|
||||
Array.prototype.unshift.call(arguments, this.wrapped);
|
||||
return _[name].apply(_, arguments);
|
||||
Array.prototype.unshift.call(arguments, this._wrapped);
|
||||
var result = _[name].apply(_, arguments);
|
||||
return this._chain ? _(result).chain() : result;
|
||||
};
|
||||
});
|
||||
|
||||
// Start chaining a wrapped Underscore object.
|
||||
wrapper.prototype.chain = function() {
|
||||
this._chain = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Extracts the result from a wrapped and chained object.
|
||||
wrapper.prototype.get = function() {
|
||||
return this._wrapped;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user