Optimize _.forEach, cleanup _.after and _.isArguments.

Former-commit-id: 3e3e9539ee6429a72f74f184f45f9c4c52bb621a
This commit is contained in:
John-David Dalton
2012-05-14 18:48:53 -04:00
parent 36df8f7828
commit 9ef0d9084f

View File

@@ -202,33 +202,11 @@
'interpolate': reInterpolateDelimiter 'interpolate': reInterpolateDelimiter
}); });
/** Reusable iterator options for `_.every` */ /**
var everyIteratorOptions = { * Reusable iterator options shared by
'init': 'true', * `every`, `filter`, `find`, `forEach`,`groupBy`, `map`, `reject`, and `some`.
'inLoop': 'if (!callback(collection[index], index, collection)) return !result' */
}; var baseIteratorOptions = {
/** Reusable iterator options for `_.extend` */
var extendIteratorOptions = {
'args': 'object',
'init': 'object',
'top':
'for (var source, sourceIndex = 1, length = arguments.length; sourceIndex < length; sourceIndex++) {\n' +
' source = arguments[sourceIndex]',
'loopExp': 'index in source',
'useHas': false,
'inLoop': 'object[index] = source[index]',
'bottom': '}'
};
/** Reusable iterator options for `_.filter` */
var filterIteratorOptions = {
'init': '[]',
'inLoop': 'callback(collection[index], index, collection) && result.push(collection[index])'
};
/** Reusable iterator options for `_.forEach` */
var forEachIteratorOptions = {
'args': 'collection, callback, thisArg', 'args': 'collection, callback, thisArg',
'init': 'collection', 'init': 'collection',
'top': 'top':
@@ -241,7 +219,32 @@
'inLoop': 'callback(collection[index], index, collection)' 'inLoop': 'callback(collection[index], index, collection)'
}; };
/** Reusable iterator options for `_.map` */ /** Reusable iterator options for `every` and `some` */
var everyIteratorOptions = {
'init': 'true',
'inLoop': 'if (!callback(collection[index], index, collection)) return !result'
};
/** Reusable iterator options for `defaults` and `extend` */
var extendIteratorOptions = {
'args': 'object',
'init': 'object',
'top':
'for (var source, sourceIndex = 1, length = arguments.length; sourceIndex < length; sourceIndex++) {\n' +
' source = arguments[sourceIndex]',
'loopExp': 'index in source',
'useHas': false,
'inLoop': 'object[index] = source[index]',
'bottom': '}'
};
/** Reusable iterator options for `filter` and `reject` */
var filterIteratorOptions = {
'init': '[]',
'inLoop': 'callback(collection[index], index, collection) && result.push(collection[index])'
};
/** Reusable iterator options for `map`, `pluck`, and `values` */
var mapIteratorOptions = { var mapIteratorOptions = {
'init': '', 'init': '',
'exit': 'if (!collection) return []', 'exit': 'if (!collection) return []',
@@ -548,7 +551,7 @@
* _.every([true, 1, null, 'yes'], Boolean); * _.every([true, 1, null, 'yes'], Boolean);
* => false * => false
*/ */
var every = createIterator(forEachIteratorOptions, everyIteratorOptions); var every = createIterator(baseIteratorOptions, everyIteratorOptions);
/** /**
* Examines each value in a `collection`, returning an array of all values the * Examines each value in a `collection`, returning an array of all values the
@@ -569,7 +572,7 @@
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [2, 4, 6] * // => [2, 4, 6]
*/ */
var filter = createIterator(forEachIteratorOptions, filterIteratorOptions); var filter = createIterator(baseIteratorOptions, filterIteratorOptions);
/** /**
* Examines each value in a `collection`, returning the first one the `callback` * Examines each value in a `collection`, returning the first one the `callback`
@@ -591,7 +594,7 @@
* var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => 2 * // => 2
*/ */
var find = createIterator(forEachIteratorOptions, { var find = createIterator(baseIteratorOptions, {
'inLoop': 'if (callback(collection[index], index, collection)) return collection[index]' 'inLoop': 'if (callback(collection[index], index, collection)) return collection[index]'
}); });
@@ -617,7 +620,12 @@
* _.forEach({ 'one': 1, 'two': 2, 'three': 3}, function(num) { alert(num); }); * _.forEach({ 'one': 1, 'two': 2, 'three': 3}, function(num) { alert(num); });
* // => alerts each number in turn... * // => alerts each number in turn...
*/ */
var forEach = createIterator(forEachIteratorOptions); var forEach = createIterator(baseIteratorOptions, {
'top':
'if (callback && thisArg) {\n' +
' callback = bind(callback, thisArg)\n' +
'}'
});
/** /**
* Splits a `collection` into sets, grouped by the result of running each value * Splits a `collection` into sets, grouped by the result of running each value
@@ -641,7 +649,7 @@
* _.groupBy(['one', 'two', 'three'], 'length'); * _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] } * // => { '3': ['one', 'two'], '5': ['three'] }
*/ */
var groupBy = createIterator(forEachIteratorOptions, { var groupBy = createIterator(baseIteratorOptions, {
'init': '{}', 'init': '{}',
'top': 'top':
'var prop, isFunc = toString.call(callback) == funcClass;\n' + 'var prop, isFunc = toString.call(callback) == funcClass;\n' +
@@ -675,7 +683,7 @@
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
* // => [3, 6, 9] * // => [3, 6, 9]
*/ */
var map = createIterator(forEachIteratorOptions, mapIteratorOptions); var map = createIterator(baseIteratorOptions, mapIteratorOptions);
/** /**
* Retrieves the value of a specified property from all values in a `collection`. * Retrieves the value of a specified property from all values in a `collection`.
@@ -820,7 +828,7 @@
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [1, 3, 5] * // => [1, 3, 5]
*/ */
var reject = createIterator(forEachIteratorOptions, filterIteratorOptions, { var reject = createIterator(baseIteratorOptions, filterIteratorOptions, {
'inLoop': '!' + filterIteratorOptions.inLoop 'inLoop': '!' + filterIteratorOptions.inLoop
}); });
@@ -910,7 +918,7 @@
* _.some([null, 0, 'yes', false]); * _.some([null, 0, 'yes', false]);
* // => true * // => true
*/ */
var some = createIterator(forEachIteratorOptions, everyIteratorOptions, { var some = createIterator(baseIteratorOptions, everyIteratorOptions, {
'init': 'false', 'init': 'false',
'inLoop': everyIteratorOptions.inLoop.replace('!', '') 'inLoop': everyIteratorOptions.inLoop.replace('!', '')
}); });
@@ -981,7 +989,7 @@
* _.compact([0, 1, false, 2, '', 3]); * _.compact([0, 1, false, 2, '', 3]);
* // => [1, 2, 3] * // => [1, 2, 3]
*/ */
var compact = function(array) { function compact(array) {
var index = -1, var index = -1,
length = array.length, length = array.length,
result = []; result = [];
@@ -1623,12 +1631,12 @@
/** /**
* Creates a new function that is restricted to executing only after it is * Creates a new function that is restricted to executing only after it is
* called a given number of `times`. * called `n` times.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Functions * @category Functions
* @param {Number} times The number of times the function must be called before * @param {Number} n The number of times the function must be called before
* it is executed. * it is executed.
* @param {Function} func The function to restrict. * @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function. * @returns {Function} Returns the new restricted function.
@@ -1640,12 +1648,12 @@
* }); * });
* // renderNotes is run once, after all notes have saved. * // renderNotes is run once, after all notes have saved.
*/ */
function after(times, func) { function after(n, func) {
if (times < 1) { if (n < 1) {
return func(); return func();
} }
return function() { return function() {
if (--times < 1) { if (--n < 1) {
return func.apply(this, arguments); return func.apply(this, arguments);
} }
}; };
@@ -2180,7 +2188,7 @@
* _.isArguments([1, 2, 3]); * _.isArguments([1, 2, 3]);
* // => false * // => false
*/ */
var isArguments = function isArguments(value) { var isArguments = function(value) {
return toString.call(value) == '[object Arguments]'; return toString.call(value) == '[object Arguments]';
}; };
// fallback for browser like IE<9 which detect `arguments` as `[object Object]` // fallback for browser like IE<9 which detect `arguments` as `[object Object]`