diff --git a/Rakefile b/Rakefile index 6af14bb6d..1b5d91615 100644 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,27 @@ require 'rubygems' require 'closure-compiler' - + desc "Use the Closure Compiler to compress Underscore.js" task :build do js = File.open('underscore.js', 'r') min = Closure::Compiler.new.compile(js) File.open('underscore-min.js', 'w') {|f| f.write(min) } -end \ No newline at end of file +end + +task :build_advanced do + js = File.read('underscore.js') + # remove wrapping anonymous function as this messes with closure compiler + # see + # http://groups.google.com/group/closure-compiler-discuss/browse_thread/thread/b59b54c1a0073aa5 + js.sub!('(function() {', '').chomp!("_.initWrapper();\n})();\n") + compiler = Closure::Compiler.new \ + :compilation_level => 'ADVANCED_OPTIMIZATIONS', + :formatting => 'PRETTY_PRINT' + min = compiler.compile(js) + File.open('underscore-min2.js', 'w') {|f| f.write(min) } + # + original_size = js.length + minimized_size = min.length + puts original_size, minimized_size +end + diff --git a/test/objects.js b/test/objects.js index 71e46bdb6..d93d72616 100644 --- a/test/objects.js +++ b/test/objects.js @@ -11,7 +11,7 @@ $(document).ready(function() { }); test("objects: functions", function() { - var expected = ["alias", "all", "any", "bind", "bindAll", "breakLoop", "buildLookup", "clone", "compact", + var expected = ["all", "any", "bind", "bindAll", "breakLoop", "buildLookup", "clone", "compact", "compose","defer", "delay", "detect", "each", "every", "extend", "filter", "first", "flatten", "foldl", "foldr", "forEach", "functions", "head", "identity", "include", "indexOf", "inject", "intersect", "invoke", "isArguments", "isArray", "isDate", "isElement", "isEmpty", "isEqual", @@ -19,7 +19,7 @@ $(document).ready(function() { "methods", "min", "noConflict", "pluck", "range", "reduce", "reduceRight", "reject", "rest", "select", "size", "some", "sortBy", "sortedIndex", "tail", "tap", "template", "times", "toArray", "uniq", "uniqueId", "values", "without", "wrap", "zip"]; - ok(_(expected).isEqual(_.methods(_)), 'provides a sorted list of functions'); + same(expected, _.methods(_), 'provides a sorted list of functions'); var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object'); }); @@ -185,19 +185,4 @@ $(document).ready(function() { value(); ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); }); - - - test("objects: alias", function() { - _.alias('isEqual', 'isTheSame'); - ok(_.isTheSame(9, 9), 'by default aliases methods on underscore'); - delete _.isTheSame; - // - var o = { hi: function () {return 9;} }; - _.alias(o, 'hi', 'ho'); - equals(o.ho(), 9, 'can add an alias on another object'); - _.alias(o, 'hi', 'there', 'sir'); - ok(o.hi==o.sir, 'can add multiple aliases'); - }); - - }); diff --git a/underscore.js b/underscore.js index 26a15e3a4..25bafb556 100644 --- a/underscore.js +++ b/underscore.js @@ -7,7 +7,6 @@ // http://documentcloud.github.com/underscore (function() { - // ------------------------- Baseline setup --------------------------------- // Establish the root object, "window" in the browser, or "global" on the server. @@ -16,53 +15,48 @@ // Save the previous value of the "_" variable. var previousUnderscore = root._; - // 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. Wrapped objects may be chained. - var wrapper = function(obj) { this._wrapped = obj; }; - // Establish the object that gets thrown to break out of a loop iteration. var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__'; - // Create a safe reference to the Underscore object for reference below. - var _ = root._ = function(obj) { return new wrapper(obj); }; - - // Export the Underscore object for CommonJS. - if (typeof exports !== 'undefined') exports._ = _; - // Quick regexp-escaping function, because JS doesn't have RegExp.escape(). var escapeRegExp = function(s) { return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); }; - + // Save bytes in the minified (but not gzipped) version: - var ArrayPrototype = Array.prototype; + var Array_Prototype = Array.prototype; // Create quick reference variables for speed access to core prototypes. - var slice = ArrayPrototype.slice, - unshift = ArrayPrototype.unshift, + var slice = Array_Prototype.slice, + unshift = Array_Prototype.unshift, toString = Object.prototype.toString, hasOwnProperty = Object.prototype.hasOwnProperty, propertyIsEnumerable = Object.prototype.propertyIsEnumerable; // All native implementations we hope to use are declared here. - // 'native' is on the long list of reserved words. - // Ok to use as a property name, though jsLint doesn't agree. - var Native = _['native'] = { - forEach: ArrayPrototype.forEach, - map: ArrayPrototype.map, - reduce: ArrayPrototype.reduce, - reduceRight: ArrayPrototype.reduceRight, - filter: ArrayPrototype.filter, - every: ArrayPrototype.every, - some: ArrayPrototype.some, - indexOf: ArrayPrototype.indexOf, - lastIndexOf: ArrayPrototype.lastIndexOf, - isArray: Array.isArray, - keys: Object.keys - }; + var + native_forEach = Array_Prototype.forEach, + native_map = Array_Prototype.map, + native_reduce = Array_Prototype.reduce, + native_reduceRight = Array_Prototype.reduceRight, + native_filter = Array_Prototype.filter, + native_every = Array_Prototype.every, + native_some = Array_Prototype.some, + native_indexOf = Array_Prototype.indexOf, + native_lastIndexOf = Array_Prototype.lastIndexOf, + native_isArray = Array['isArray'], // use [] notation since not in closure's externs + native_keys = Object['keys']; + + // Create a safe reference to the Underscore object for reference below. + var _ = function(obj) { return _.buildWrapper(obj) }; + + // Export the Underscore object for CommonJS. + if (typeof exports !== 'undefined') exports._ = _; + + // Export underscore to global scope. + root._ = _; // Current version. _.VERSION = '0.5.8'; - + // ------------------------ Collection Functions: --------------------------- // The cornerstone, an each implementation. @@ -72,13 +66,16 @@ _.forEach = function(obj, iterator, context) { var index = 0; try { - if (obj.forEach === Native.forEach) { + if (obj.forEach === native_forEach) { obj.forEach(iterator, context); } else if (_.isNumber(obj.length)) { for (var i=0, l=obj.length; i