mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-07 10:07:48 +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>
|
<p>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<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>
|
<td><i>16kb, Uncompressed with Comments</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
<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>
|
<td><i>2kb, Packed and Gzipped</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</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>
|
<h2>Table of Contents</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -742,6 +781,17 @@ moe === _.identity(moe);
|
|||||||
<pre>
|
<pre>
|
||||||
_.uniqueId('contact_');
|
_.uniqueId('contact_');
|
||||||
=> 'contact_104'
|
=> '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>
|
</pre>
|
||||||
|
|
||||||
<p id="template">
|
<p id="template">
|
||||||
@@ -769,6 +819,16 @@ _.template(list, {people : ['moe', 'curly', 'larry']});
|
|||||||
|
|
||||||
<h2>Change Log</h2>
|
<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>
|
<p>
|
||||||
<b class="header">0.3.3</b><br />
|
<b class="header">0.3.3</b><br />
|
||||||
Added the JavaScript 1.8 function <tt>reduceRight</tt>. Aliased it
|
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
|
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
|
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
|
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>
|
||||||
|
|
||||||
<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="functions.js"></script>
|
||||||
<script type="text/javascript" src="objects.js"></script>
|
<script type="text/javascript" src="objects.js"></script>
|
||||||
<script type="text/javascript" src="utility.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>
|
<script type="text/javascript" src="speed.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ $(document).ready(function() {
|
|||||||
equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
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() {
|
test("utility: template", function() {
|
||||||
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
||||||
var result = basicTemplate({thing : 'This'});
|
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
|
// 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
|
// can be used OO-style. This wrapper holds altered versions of all the
|
||||||
// underscore functions.
|
// underscore functions. Wrapped objects may be chained.
|
||||||
var wrapper = function(obj) { this.wrapped = obj; };
|
var wrapper = function(obj) { this._wrapped = obj; };
|
||||||
|
|
||||||
// Create a safe reference to the Underscore object for reference below.
|
// Create a safe reference to the Underscore object for reference below.
|
||||||
var _ = root._ = function(obj) { return new wrapper(obj); };
|
var _ = root._ = function(obj) { return new wrapper(obj); };
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
if (typeof exports !== 'undefined') _ = exports;
|
if (typeof exports !== 'undefined') _ = exports;
|
||||||
|
|
||||||
// Current version.
|
// Current version.
|
||||||
_.VERSION = '0.3.3';
|
_.VERSION = '0.4.0';
|
||||||
|
|
||||||
/*------------------------ Collection Functions: ---------------------------*/
|
/*------------------------ Collection Functions: ---------------------------*/
|
||||||
|
|
||||||
@@ -447,8 +447,9 @@
|
|||||||
|
|
||||||
// Generate a unique integer id (unique within the entire client session).
|
// Generate a unique integer id (unique within the entire client session).
|
||||||
// Useful for temporary DOM ids.
|
// Useful for temporary DOM ids.
|
||||||
|
var idCounter = 0;
|
||||||
_.uniqueId = function(prefix) {
|
_.uniqueId = function(prefix) {
|
||||||
var id = this._idCounter = (this._idCounter || 0) + 1;
|
var id = idCounter++;
|
||||||
return prefix ? prefix + id : id;
|
return prefix ? prefix + id : id;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -456,7 +457,7 @@
|
|||||||
_.functions = function() {
|
_.functions = function() {
|
||||||
var functions = [];
|
var functions = [];
|
||||||
for (var key in _) if (Object.prototype.hasOwnProperty.call(_, key)) functions.push(key);
|
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
|
// JavaScript templating a-la ERB, pilfered from John Resig's
|
||||||
@@ -487,13 +488,26 @@
|
|||||||
_.some = _.any;
|
_.some = _.any;
|
||||||
_.methods = _.functions;
|
_.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) {
|
_.each(_.functions(), function(name) {
|
||||||
wrapper.prototype[name] = function() {
|
wrapper.prototype[name] = function() {
|
||||||
Array.prototype.unshift.call(arguments, this.wrapped);
|
Array.prototype.unshift.call(arguments, this._wrapped);
|
||||||
return _[name].apply(_, arguments);
|
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