diff --git a/test/objects.js b/test/objects.js index ac56c495f..e45633e8c 100644 --- a/test/objects.js +++ b/test/objects.js @@ -16,7 +16,7 @@ $(document).ready(function() { "flatten", "foldl", "foldr", "forEach", "functions", "head", "identity", "include", "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", + "methods", "min", "mixin", "noConflict", "pluck", "range", "reduce", "reduceRight", "reject", "rest", "select", "size", "some", "sortBy", "sortedIndex", "tail", "tap", "template", "times", "toArray", "uniq", "uniqueId", "values", "without", "wrap", "zip"]; same(expected, _.methods(_), 'provides a sorted list of functions'); diff --git a/test/utility.js b/test/utility.js index 1b365d2be..c9498c227 100644 --- a/test/utility.js +++ b/test/utility.js @@ -29,7 +29,7 @@ $(document).ready(function() { while(i++ < 100) ids.push(_.uniqueId()); equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); }); - + test("utility: times", function() { var vals = []; _.times(3, function (i) { vals.push(i); }); @@ -39,7 +39,16 @@ $(document).ready(function() { _(3).times(function (i) { vals.push(i); }); ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); }); - + + test("utility: mixin", function() { + _.mixin({ + myReverse: function(string) { + return string.split('').reverse().join(''); + } + }); + equals(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); + equals(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); + }); test("utility: template", function() { var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); diff --git a/underscore.js b/underscore.js index 42770faeb..87034bd2e 100644 --- a/underscore.js +++ b/underscore.js @@ -31,7 +31,7 @@ hasOwnProperty = ObjProto.hasOwnProperty, propertyIsEnumerable = ObjProto.propertyIsEnumerable; - // All native implementations we hope to use are declared here. + // All ECMA5 native implementations we hope to use are declared here. var nativeForEach = ArrayProto.forEach, nativeMap = ArrayProto.map, @@ -50,6 +50,15 @@ // underscore functions. Wrapped objects may be chained. var wrapper = function(obj) { this._wrapped = obj; }; + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = _.toArray(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + // Create a safe reference to the Underscore object for reference below. var _ = function(obj) { return new wrapper(obj); }; @@ -431,7 +440,7 @@ return _.map(obj, _.identity); }; - // Return a sorted list of the function names available in Underscore. + // Return a sorted list of the function names available on the object. _.functions = function(obj) { return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort(); }; @@ -579,6 +588,14 @@ throw breaker; }; + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + // Generate a unique integer id (unique within the entire client session). // Useful for temporary DOM ids. var idCounter = 0; @@ -634,14 +651,7 @@ }; // Add all of the Underscore functions to the wrapper object. - each(_.functions(_), function(name) { - var method = _[name]; - wrapper.prototype[name] = function() { - var args = _.toArray(arguments); - unshift.call(args, this._wrapped); - return result(method.apply(_, args), this._chain); - }; - }); + _.mixin(_); // Add all mutator Array functions to the wrapper. each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {