diff --git a/index.html b/index.html index 06de0f1b9..dc65e3f33 100644 --- a/index.html +++ b/index.html @@ -81,7 +81,7 @@

- Underscore provides 45-odd functions that support both the usual + Underscore provides 50-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 @@ -107,11 +107,11 @@

- + - +
Development Version (0.4.0)Development Version (0.4.1) 18kb, Uncompressed with Comments
Production Version (0.4.0)Production Version (0.4.1) 2kb, Packed and Gzipped
@@ -156,6 +156,14 @@ _(lyrics).chain() => {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

@@ -860,8 +868,13 @@ _.template(list, {people : ['moe', 'curly', 'larry']}); A more realistic example.)

-_({moe : false, curly : true}).chain().values().any().isEqual(true).get();
-=> true
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _(stooges).chain()
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .get();
+=> "moe is 21"
 

@@ -875,6 +888,15 @@ _([1, 2, 3]).get();

Change Log

+ +

+ 0.4.1
+ Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

0.4.0
diff --git a/test/chaining.js b/test/chaining.js index 0f3b10037..dc6cef6a4 100644 --- a/test/chaining.js +++ b/test/chaining.js @@ -1,7 +1,7 @@ $(document).ready(function() { - + module("Underscore chaining."); - + test("chaining: map/flatten/reduce", function() { var lyrics = [ "I'm a lumberjack and I'm okay", @@ -12,14 +12,14 @@ $(document).ready(function() { var counts = _(lyrics).chain() .map(function(line) { return line.split(''); }) .flatten() - .reduce({}, function(hash, l) { + .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) { @@ -31,5 +31,17 @@ $(document).ready(function() { }).get(); equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); }); - + + test("chaining: reverse/concat/unshift/pop/map", function() { + var numbers = [1,2,3,4,5]; + numbers = _(numbers).chain() + .reverse() + .concat([5, 5, 5]) + .unshift(17) + .pop() + .map(function(n){ return n * 2; }) + .get(); + equals(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.'); + }); + }); diff --git a/underscore-min.js b/underscore-min.js index 25ad77f4c..e0fd42d76 100644 --- a/underscore-min.js +++ b/underscore-min.js @@ -1 +1 @@ -(function(){var b=this;var d=b._;var e=function(f){this._wrapped=f};var c=b._=function(f){return new e(f)};if(typeof exports!=="undefined"){c=exports}c.VERSION="0.4.0";c.each=function(o,m,k){var g=0;try{if(o.forEach){o.forEach(m,k)}else{if(o.length){for(var j=0,f=o.length;j=f.computed&&(f={value:o,computed:m})});return f.value};c.min=function(j,h,g){if(!h&&c.isArray(j)){return Math.min.apply(Math,j)}var f={computed:Infinity};c.each(j,function(o,k,n){var m=h?h.call(g,o,k,n):o;mj?1:0}),"value")};c.sortedIndex=function(m,k,h){h=h||c.identity;var f=0,j=m.length;while(f>1;h(m[g])=0})})};c.zip=function(){var f=c.toArray(arguments);var j=c.max(c.pluck(f,"length"));var h=new Array(j);for(var g=0;g=0;g--){arguments=[f[g].apply(this,arguments)]}return arguments[0]}};c.keys=function(f){return c.map(f,function(h,g){return g})};c.values=function(f){return c.map(f,c.identity)};c.extend=function(f,h){for(var g in h){f[g]=h[g]}return f};c.clone=function(f){if(c.isArray(f)){return f.slice(0)}return c.extend({},f)};c.isEqual=function(g,f){if(g===f){return true}var k=typeof(g),n=typeof(f);if(k!=n){return false}if(g==f){return true}if(g.isEqual){return g.isEqual(f)}if(k!=="object"){return false}var h=c.keys(g),m=c.keys(f);if(h.length!=m.length){return false}for(var j in g){if(!c.isEqual(g[j],f[j])){return false}}return true};c.isElement=function(f){return !!(f&&f.nodeType==1)};c.isArray=function(f){return Object.prototype.toString.call(f)=="[object Array]"};c.isFunction=function(f){return Object.prototype.toString.call(f)=="[object Function]"};c.isUndefined=function(f){return typeof f=="undefined"};c.noConflict=function(){b._=d;return this};c.identity=function(f){return f};var a=0;c.uniqueId=function(f){var g=a++;return f?f+g:g};c.functions=function(){var g=[];for(var f in c){if(Object.prototype.hasOwnProperty.call(c,f)){g.push(f)}}return c.without(g,"VERSION","prototype","noConflict").sort()};c.template=function(h,g){var f=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+h.replace(/[\r\t\n]/g," ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');");return g?f(g):f};c.forEach=c.each;c.foldl=c.inject=c.reduce;c.foldr=c.reduceRight;c.filter=c.select;c.every=c.all;c.some=c.any;c.methods=c.functions;c.each(c.functions(),function(f){e.prototype[f]=function(){Array.prototype.unshift.call(arguments,this._wrapped);var g=c[f].apply(c,arguments);return this._chain?c(g).chain():g}});e.prototype.chain=function(){this._chain=true;return this};e.prototype.get=function(){return this._wrapped}})(); \ No newline at end of file +(function(){var c=this;var e=c._;var f=function(g){this._wrapped=g};var d=c._=function(g){return new f(g)};if(typeof exports!=="undefined"){d=exports}d.VERSION="0.4.1";d.each=function(p,n,m){var h=0;try{if(p.forEach){p.forEach(n,m)}else{if(p.length){for(var k=0,g=p.length;k=g.computed&&(g={value:p,computed:n})});return g.value};d.min=function(k,j,h){if(!j&&d.isArray(k)){return Math.min.apply(Math,k)}var g={computed:Infinity};d.each(k,function(p,m,o){var n=j?j.call(h,p,m,o):p;nk?1:0}),"value")};d.sortedIndex=function(n,m,j){j=j||d.identity;var g=0,k=n.length;while(g>1;j(n[h])=0})})};d.zip=function(){var g=d.toArray(arguments);var k=d.max(d.pluck(g,"length"));var j=new Array(k);for(var h=0;h=0;h--){arguments=[g[h].apply(this,arguments)]}return arguments[0]}};d.keys=function(g){return d.map(g,function(j,h){return h})};d.values=function(g){return d.map(g,d.identity)};d.extend=function(g,j){for(var h in j){g[h]=j[h]}return g};d.clone=function(g){if(d.isArray(g)){return g.slice(0)}return d.extend({},g)};d.isEqual=function(h,g){if(h===g){return true}var m=typeof(h),o=typeof(g);if(m!=o){return false}if(h==g){return true}if(h.isEqual){return h.isEqual(g)}if(m!=="object"){return false}var j=d.keys(h),n=d.keys(g);if(j.length!=n.length){return false}for(var k in h){if(!d.isEqual(h[k],g[k])){return false}}return true};d.isEmpty=function(g){return(d.isArray(g)?g:d.values(g)).length==0};d.isElement=function(g){return !!(g&&g.nodeType==1)};d.isArray=function(g){return Object.prototype.toString.call(g)=="[object Array]"};d.isFunction=function(g){return Object.prototype.toString.call(g)=="[object Function]"};d.isUndefined=function(g){return typeof g=="undefined"};d.noConflict=function(){c._=e;return this};d.identity=function(g){return g};d.breakLoop=function(){throw"__break__"};var b=0;d.uniqueId=function(g){var h=b++;return g?g+h:h};d.functions=function(){var h=[];for(var g in d){if(Object.prototype.hasOwnProperty.call(d,g)){h.push(g)}}return d.without(h,"VERSION","prototype","noConflict").sort()};d.template=function(j,h){var g=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+j.replace(/[\r\t\n]/g," ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');");return h?g(h):g};d.forEach=d.each;d.foldl=d.inject=d.reduce;d.foldr=d.reduceRight;d.filter=d.select;d.every=d.all;d.some=d.any;d.methods=d.functions;var a=function(h,g){return g?d(h).chain():h};d.each(d.functions(),function(g){f.prototype[g]=function(){Array.prototype.unshift.call(arguments,this._wrapped);return a(d[g].apply(d,arguments),this._chain)}});d.each(["pop","push","reverse","shift","sort","splice","unshift"],function(g){f.prototype[g]=function(){Array.prototype[g].apply(this._wrapped,arguments);return a(this._wrapped,this._chain)}});d.each(["concat","join","slice"],function(g){f.prototype[g]=function(){return a(Array.prototype[g].apply(this._wrapped,arguments),this._chain)}});f.prototype.chain=function(){this._chain=true;return this};f.prototype.get=function(){return this._wrapped}})(); \ No newline at end of file diff --git a/underscore.js b/underscore.js index 748c6e247..c0fedb145 100644 --- a/underscore.js +++ b/underscore.js @@ -28,7 +28,7 @@ if (typeof exports !== 'undefined') _ = exports; // Current version. - _.VERSION = '0.4.0'; + _.VERSION = '0.4.1'; /*------------------------ Collection Functions: ---------------------------*/ @@ -496,12 +496,31 @@ /*------------------------ Setup the OOP Wrapper: --------------------------*/ + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + // 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); - var result = _[name].apply(_, arguments); - return this._chain ? _(result).chain() : result; + return result(_[name].apply(_, arguments), this._chain); + }; + }); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + wrapper.prototype[name] = function() { + Array.prototype[name].apply(this._wrapped, arguments); + return result(this._wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + wrapper.prototype[name] = function() { + return result(Array.prototype[name].apply(this._wrapped, arguments), this._chain); }; });