diff --git a/backbone.js b/backbone.js index 99e5a15bb..af65dbca3 100644 --- a/backbone.js +++ b/backbone.js @@ -68,6 +68,9 @@ // form param named `model`. Backbone.emulateJSON = false; + // A cached regex to detect if the Underscore function contains the `arguments` + // keyword. + var containsArguments = /\barguments\b/; // Proxy Backbone class methods to Underscore functions, wrapping the model's // `attributes` object or collection's `models` array behind the scenes. // @@ -76,6 +79,10 @@ // // `Function#apply` can be slow so we use the method's arg count, if we know it. var addMethod = function(length, method, attribute) { + // In case we don't catch it, deopt Underscore functions that contain + // the arguments keyword. + if (length > 0 && containsArguments.test(_[method])) length = 0; + switch (length) { case 1: return function() { return _[method](this[attribute]); @@ -87,9 +94,6 @@ return _[method](this[attribute], cb(iteratee, this), context); }; case 4: return function(iteratee, defaultVal, context) { - if(arguments.length < 2) { - return _[method](this[attribute], cb(iteratee, this)); - } return _[method](this[attribute], cb(iteratee, this), defaultVal, context); }; default: return function() { @@ -1169,8 +1173,8 @@ // Underscore methods that we want to implement on the Collection. // 90% of the core usefulness of Backbone Collections is actually implemented // right here: - var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4, - foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3, + var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 0, + foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3, select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3, contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,