diff --git a/index.html b/index.html index 894ec25d7..b7a368b34 100644 --- a/index.html +++ b/index.html @@ -206,7 +206,7 @@ _(lyrics).chain() Objects
keys, values, - functions, extend, clone, + functions, extend, clone, tap, isEqual, isEmpty, isElement, isArray, isArguments, isFunction, isString, isNumber, isDate, isRegExp @@ -766,6 +766,22 @@ _.extend({name : 'moe'}, {age : 50});
 _.clone({name : 'moe'});
 => {name : 'moe'};
+
+ +

+ tap_.tap(object, interceptor) +
+ Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

+
+_([1,2,3,200]).chain().
+  select(function(num) { return num % 2 == 0; }).
+  tap(console.log).
+  map(function(num) { return num * num }).
+  value();
+=> [2, 200]
+=> [4, 40000]
 

diff --git a/test/objects.js b/test/objects.js index cd45c0bc6..b8affa46e 100644 --- a/test/objects.js +++ b/test/objects.js @@ -17,7 +17,7 @@ $(document).ready(function() { "indexOf", "inject", "intersect", "invoke", "isArguments", "isArray", "isDate", "isElement", "isEmpty", "isEqual", "isFunction", "isNaN", "isNull", "isNumber", "isRegExp", "isString", "isUndefined", "keys", "last", "lastIndexOf", "map", "max", "methods", "min", "noConflict", "pluck", "range", "reduce", "reduceRight", "reject", "rest", "select", - "size", "some", "sortBy", "sortedIndex", "tail", "template", "toArray", "uniq", + "size", "some", "sortBy", "sortedIndex", "tail", "tap", "template", "toArray", "uniq", "uniqueId", "values", "without", "wrap", "zip"]; ok(_(expected).isEqual(_.methods(_)), 'provides a sorted list of functions'); var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; @@ -131,4 +131,18 @@ $(document).ready(function() { ok(_.isUndefined(undefined), 'undefined is undefined'); }); + test("objects: tap", function() { + var intercepted = null; + var interceptor = function(obj) { intercepted = obj; }; + var returned = _.tap(1, interceptor); + equals(intercepted, 1, "passes tapped object to interceptor"); + equals(returned, 1, "returns tapped object"); + + returned = _([1,2,3]).chain(). + map(function(n){ return n * 2; }). + max(). + tap(interceptor). + value(); + ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); + }); }); diff --git a/underscore.js b/underscore.js index 047f01c59..8a6d9e0c5 100644 --- a/underscore.js +++ b/underscore.js @@ -495,6 +495,13 @@ return typeof obj == 'undefined'; }; + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + } + // Define the isArray, isDate, isFunction, isNumber, isRegExp, and isString // functions based on their toString identifiers. var types = ['Array', 'Date', 'Function', 'Number', 'RegExp', 'String'];