mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-01 07:47:49 +00:00
Make a private each function to be used by _.forEach.
Former-commit-id: da9e22a66aef1ad9f4688f4fbb07e0806f8f0445
This commit is contained in:
51
build.js
51
build.js
@@ -73,7 +73,7 @@
|
||||
'clone': ['assign', 'forEach', 'forOwn', 'isArray', 'isObject'],
|
||||
'compact': [],
|
||||
'compose': [],
|
||||
'contains': ['forEach', 'indexOf', 'isString'],
|
||||
'contains': ['indexOf', 'isString'],
|
||||
'countBy': ['forEach'],
|
||||
'debounce': [],
|
||||
'defaults': ['isArguments'],
|
||||
@@ -81,12 +81,12 @@
|
||||
'delay': [],
|
||||
'difference': ['indexOf'],
|
||||
'escape': [],
|
||||
'every': ['forEach', 'isArray'],
|
||||
'filter': ['forEach', 'isArray'],
|
||||
'every': ['isArray'],
|
||||
'filter': ['isArray'],
|
||||
'find': ['forEach'],
|
||||
'first': [],
|
||||
'flatten': ['isArray'],
|
||||
'forEach': ['identity', 'isArguments', 'isString'],
|
||||
'forEach': ['identity', 'isArguments', 'isArray', 'isString'],
|
||||
'forIn': ['identity', 'isArguments'],
|
||||
'forOwn': ['identity', 'isArguments'],
|
||||
'functions': ['forIn', 'isFunction'],
|
||||
@@ -95,7 +95,7 @@
|
||||
'identity': [],
|
||||
'indexOf': ['sortedIndex'],
|
||||
'initial': [],
|
||||
'intersection': ['filter', 'indexOf'],
|
||||
'intersection': ['forEach', 'indexOf'],
|
||||
'invert': ['forOwn'],
|
||||
'invoke': ['forEach'],
|
||||
'isArguments': [],
|
||||
@@ -118,11 +118,11 @@
|
||||
'keys': ['forOwn', 'isArguments', 'isObject'],
|
||||
'last': [],
|
||||
'lastIndexOf': [],
|
||||
'map': ['forEach', 'isArray'],
|
||||
'max': ['forEach', 'isArray', 'isString'],
|
||||
'map': ['isArray'],
|
||||
'max': ['isArray', 'isString'],
|
||||
'memoize': [],
|
||||
'merge': ['forOwn', 'isArray', 'isPlainObject'],
|
||||
'min': ['forEach', 'isArray', 'isString'],
|
||||
'min': ['isArray', 'isString'],
|
||||
'mixin': ['forEach', 'forOwn', 'functions'],
|
||||
'noConflict': [],
|
||||
'object': [],
|
||||
@@ -134,14 +134,14 @@
|
||||
'pluck': ['map'],
|
||||
'random': [],
|
||||
'range': [],
|
||||
'reduce': ['forEach', 'isArray'],
|
||||
'reduce': ['isArray'],
|
||||
'reduceRight': ['forEach', 'isString', 'keys'],
|
||||
'reject': ['filter'],
|
||||
'rest': [],
|
||||
'result': ['isFunction'],
|
||||
'shuffle': ['forEach'],
|
||||
'size': ['keys'],
|
||||
'some': ['forEach', 'isArray'],
|
||||
'some': ['isArray'],
|
||||
'sortBy': ['forEach'],
|
||||
'sortedIndex': ['identity'],
|
||||
'tap': ['mixin'],
|
||||
@@ -368,10 +368,10 @@
|
||||
});
|
||||
|
||||
// replace wrapper `Array` method assignments
|
||||
source = source.replace(/^(?: *\/\/.*\n)*( *)forEach\(\['[\s\S]+?\n\1}$/m, function() {
|
||||
source = source.replace(/^(?: *\/\/.*\n)*( *)each\(\['[\s\S]+?\n\1}$/m, function() {
|
||||
return [
|
||||
' // add `Array` mutator functions to the wrapper',
|
||||
" forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {",
|
||||
" each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {",
|
||||
' var func = arrayRef[methodName];',
|
||||
' lodash.prototype[methodName] = function() {',
|
||||
' var value = this.__wrapped__;',
|
||||
@@ -387,7 +387,7 @@
|
||||
' });',
|
||||
'',
|
||||
' // add `Array` accessor functions to the wrapper',
|
||||
" forEach(['concat', 'join', 'slice'], function(methodName) {",
|
||||
" each(['concat', 'join', 'slice'], function(methodName) {",
|
||||
' var func = arrayRef[methodName];',
|
||||
' lodash.prototype[methodName] = function() {',
|
||||
' var value = this.__wrapped__,',
|
||||
@@ -1274,11 +1274,11 @@
|
||||
dependencyMap.reduceRight = ['forEach', 'keys'];
|
||||
}
|
||||
if (isUnderscore) {
|
||||
dependencyMap.contains = ['forEach', 'indexOf'];
|
||||
dependencyMap.contains = ['indexOf'];
|
||||
dependencyMap.isEqual = ['isArray', 'isFunction'];
|
||||
dependencyMap.isEmpty = ['isArray', 'isString'];
|
||||
dependencyMap.max = ['forEach', 'isArray'];
|
||||
dependencyMap.min = ['forEach', 'isArray'];
|
||||
dependencyMap.max = ['isArray'];
|
||||
dependencyMap.min = ['isArray'];
|
||||
dependencyMap.pick = [];
|
||||
dependencyMap.template = ['defaults', 'escape'];
|
||||
|
||||
@@ -1390,7 +1390,7 @@
|
||||
" if (typeof length == 'number') {",
|
||||
' result = indexOf(collection, target) > -1;',
|
||||
' } else {',
|
||||
' forEach(collection, function(value) {',
|
||||
' each(collection, function(value) {',
|
||||
' return (result = value === target) && indicatorObject;',
|
||||
' });',
|
||||
' }',
|
||||
@@ -1734,7 +1734,8 @@
|
||||
if (isMobile) {
|
||||
// inline all functions defined with `createIterator`
|
||||
_.functions(lodash).forEach(function(methodName) {
|
||||
var reFunc = RegExp('(\\bvar ' + methodName + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n');
|
||||
// strip leading underscores to match pseudo private functions
|
||||
var reFunc = RegExp('(\\bvar ' + methodName.replace(/^_/, '') + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n');
|
||||
if (reFunc.test(source)) {
|
||||
// extract, format, and inject the compiled function's source code
|
||||
source = source.replace(reFunc, function(match, captured) {
|
||||
@@ -1777,13 +1778,15 @@
|
||||
});
|
||||
}());
|
||||
|
||||
// remove chainability from `_.forEach`
|
||||
source = source.replace(matchFunction(source, 'forEach'), function(match) {
|
||||
return match.replace(/return result([};\s]+)$/, '$1');
|
||||
// remove chainability from `each` and `_.forEach`
|
||||
_.each(['each', 'forEach'], function(methodName) {
|
||||
source = source.replace(matchFunction(source, methodName), function(match) {
|
||||
return match.replace(/\n *return .+?([};\s]+)$/, '$1');
|
||||
});
|
||||
});
|
||||
|
||||
// unexpose "exit early" feature from `_.forEach`, `_.forIn`, and `_.forOwn`
|
||||
_.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
|
||||
// unexpose "exit early" feature of `each`, `_.forEach`, `_.forIn`, and `_.forOwn`
|
||||
_.each(['each', 'forEach', 'forIn', 'forOwn'], function(methodName) {
|
||||
source = source.replace(matchFunction(source, methodName), function(match) {
|
||||
return match.replace(/=== *false\)/g, '=== indicatorObject)');
|
||||
});
|
||||
@@ -1962,7 +1965,7 @@
|
||||
// remove all `lodash.prototype` additions
|
||||
source = source
|
||||
.replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, '')
|
||||
.replace(/(?:\s*\/\/.*)*\n( *)forEach\(\['[\s\S]+?\n\1}.+/g, '')
|
||||
.replace(/(?:\s*\/\/.*)*\n( *)each\(\['[\s\S]+?\n\1}.+/g, '')
|
||||
.replace(/(?:\s*\/\/.*)*\s*lodash\.prototype.+\n/g, '')
|
||||
.replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+\n/, '');
|
||||
}
|
||||
|
||||
112
lodash.js
112
lodash.js
@@ -116,8 +116,7 @@
|
||||
stringClass = '[object String]';
|
||||
|
||||
/** Detect various environments */
|
||||
var isFirefox = !/1/.test(Function('1')),
|
||||
isIeOpera = !!window.attachEvent,
|
||||
var isIeOpera = !!window.attachEvent,
|
||||
isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
|
||||
|
||||
/* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
|
||||
@@ -247,24 +246,25 @@
|
||||
* method chaining.
|
||||
*
|
||||
* The chainable wrapper functions are:
|
||||
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
|
||||
* `compose`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
|
||||
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
|
||||
* `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
|
||||
* `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
|
||||
* `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
|
||||
* `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `pick`, `pluck`,
|
||||
* `range`, `reject`, `rest`, `shuffle`, `sortBy`, `tap`, `throttle`, `times`,
|
||||
* `toArray`, `union`, `uniq`, `values`, `where`, `without`, `wrap`, and `zip`
|
||||
* `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
|
||||
* `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `union`, `uniq`,
|
||||
* `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
|
||||
*
|
||||
* The non-chainable wrapper functions are:
|
||||
* `clone`, `contains`, `escape`, `every`, `find`, `has`, `identity`, `indexOf`,
|
||||
* `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
|
||||
* `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
|
||||
* `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `lastIndexOf`, `mixin`,
|
||||
* `noConflict`, `random`, `reduce`, `reduceRight`, `result`, `size`, `some`,
|
||||
* `sortedIndex`, `template`, `unescape`, and `uniqueId`
|
||||
* `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
|
||||
* `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
|
||||
* `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
|
||||
*
|
||||
* The wrapper functions `first` and `last` return wrapped values when `n` is
|
||||
* passed, otherwise return unwrapped values.
|
||||
* passed, otherwise they return unwrapped values.
|
||||
*
|
||||
* @name _
|
||||
* @constructor
|
||||
@@ -334,25 +334,6 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a function from the given `args` and `body` strings.
|
||||
*
|
||||
* @private
|
||||
* @param {String} args The comma separated function arguments.
|
||||
* @param {String} body The function body.
|
||||
* @returns {Function} The new function.
|
||||
*/
|
||||
function createFunction(args, body) {
|
||||
// the newline, in `'\n}'`, is required to avoid errors if `body` ends
|
||||
// with a single line comment
|
||||
return window.eval('(function(' + args + ') {' + body + '\n})');
|
||||
}
|
||||
// use `eval` to avoid Firefox's unoptimized `Function` constructor
|
||||
// http://bugzil.la/804933
|
||||
if (isIeOpera || isV8 || !isFirefox) {
|
||||
createFunction = Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* The template used to create iterator functions.
|
||||
*
|
||||
@@ -476,9 +457,9 @@
|
||||
};
|
||||
|
||||
/**
|
||||
* Reusable iterator options shared by `forEach`, `forIn`, and `forOwn`.
|
||||
* Reusable iterator options shared by `each`, `forIn`, and `forOwn`.
|
||||
*/
|
||||
var forEachIteratorOptions = {
|
||||
var eachIteratorOptions = {
|
||||
'args': 'collection, callback, thisArg',
|
||||
'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
|
||||
'arrayLoop': 'if (callback(iteratee[index], index, collection) === false) return result',
|
||||
@@ -696,7 +677,7 @@
|
||||
data.firstArg = /^[^,]+/.exec(args)[0];
|
||||
|
||||
// create the function factory
|
||||
var factory = createFunction(
|
||||
var factory = Function(
|
||||
'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
|
||||
'nativeKeys, propertyIsEnumerable',
|
||||
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
||||
@@ -708,6 +689,21 @@
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function compiled to iterate `arguments` objects, arrays, objects, and
|
||||
* strings consistenly across environments, executing the `callback` for each
|
||||
* element in the `collection`. The `callback` is bound to `thisArg` and invoked
|
||||
* with three arguments; (value, index|key, collection). Callbacks may exit
|
||||
* iteration early by explicitly returning `false`.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object|String} collection The collection to iterate over.
|
||||
* @param {Function} [callback=identity] The function called per iteration.
|
||||
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
||||
* @returns {Array|Object|String} Returns `collection`.
|
||||
*/
|
||||
var each = createIterator(eachIteratorOptions);
|
||||
|
||||
/**
|
||||
* Used by `template` to escape characters for inclusion in compiled
|
||||
* string literals.
|
||||
@@ -867,7 +863,7 @@
|
||||
* });
|
||||
* // => alerts 'name' and 'bark' (order is not guaranteed)
|
||||
*/
|
||||
var forIn = createIterator(forEachIteratorOptions, forOwnIteratorOptions, {
|
||||
var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
|
||||
'useHas': false
|
||||
});
|
||||
|
||||
@@ -891,7 +887,7 @@
|
||||
* });
|
||||
* // => alerts '0', '1', and 'length' (order is not guaranteed)
|
||||
*/
|
||||
var forOwn = createIterator(forEachIteratorOptions, forOwnIteratorOptions);
|
||||
var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
|
||||
|
||||
/**
|
||||
* A fallback implementation of `isPlainObject` that checks if a given `value`
|
||||
@@ -1941,7 +1937,7 @@
|
||||
: indexOf(collection, target, fromIndex)
|
||||
) > -1;
|
||||
} else {
|
||||
forEach(collection, function(value) {
|
||||
each(collection, function(value) {
|
||||
if (++index >= fromIndex) {
|
||||
return !(result = value === target);
|
||||
}
|
||||
@@ -2020,7 +2016,7 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
forEach(collection, function(value, index, collection) {
|
||||
each(collection, function(value, index, collection) {
|
||||
return (result = !!callback(value, index, collection));
|
||||
});
|
||||
}
|
||||
@@ -2060,7 +2056,7 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
forEach(collection, function(value, index, collection) {
|
||||
each(collection, function(value, index, collection) {
|
||||
if (callback(value, index, collection)) {
|
||||
result.push(value);
|
||||
}
|
||||
@@ -2124,7 +2120,24 @@
|
||||
* _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
|
||||
* // => alerts each number value (order is not guaranteed)
|
||||
*/
|
||||
var forEach = createIterator(forEachIteratorOptions);
|
||||
function forEach(collection, callback, thisArg) {
|
||||
if (isArray(collection)) {
|
||||
var index = -1,
|
||||
length = collection.length;
|
||||
|
||||
if (!callback || typeof thisArg != 'undefined') {
|
||||
callback = createCallback(callback, thisArg);
|
||||
}
|
||||
while (++index < length) {
|
||||
if (callback(collection[index], index, collection) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
each(collection, callback, thisArg);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object composed of keys returned from running each element of
|
||||
@@ -2228,7 +2241,7 @@
|
||||
result[index] = callback(collection[index], index, collection);
|
||||
}
|
||||
} else {
|
||||
forEach(collection, function(value, key, collection) {
|
||||
each(collection, function(value, key, collection) {
|
||||
result[++index] = callback(value, key, collection);
|
||||
});
|
||||
}
|
||||
@@ -2270,7 +2283,7 @@
|
||||
? charAtCallback
|
||||
: createCallback(callback, thisArg);
|
||||
|
||||
forEach(collection, function(value, index, collection) {
|
||||
each(collection, function(value, index, collection) {
|
||||
var current = callback(value, index, collection);
|
||||
if (current > computed) {
|
||||
computed = current;
|
||||
@@ -2316,7 +2329,7 @@
|
||||
? charAtCallback
|
||||
: createCallback(callback, thisArg);
|
||||
|
||||
forEach(collection, function(value, index, collection) {
|
||||
each(collection, function(value, index, collection) {
|
||||
var current = callback(value, index, collection);
|
||||
if (current < computed) {
|
||||
computed = current;
|
||||
@@ -2393,7 +2406,7 @@
|
||||
accumulator = callback(accumulator, collection[index], index, collection);
|
||||
}
|
||||
} else {
|
||||
forEach(collection, function(value, index, collection) {
|
||||
each(collection, function(value, index, collection) {
|
||||
accumulator = noaccum
|
||||
? (noaccum = false, value)
|
||||
: callback(accumulator, value, index, collection)
|
||||
@@ -2550,7 +2563,7 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
forEach(collection, function(value, index, collection) {
|
||||
each(collection, function(value, index, collection) {
|
||||
return !(result = callback(value, index, collection));
|
||||
});
|
||||
}
|
||||
@@ -4006,7 +4019,7 @@
|
||||
: '';
|
||||
|
||||
try {
|
||||
result = createFunction('_', 'return ' + source + sourceURL)(lodash);
|
||||
result = Function('_', 'return ' + source + sourceURL)(lodash);
|
||||
} catch(e) {
|
||||
e.source = source;
|
||||
throw e;
|
||||
@@ -4136,7 +4149,7 @@
|
||||
* // => '1,2,3'
|
||||
*/
|
||||
function wrapperToString() {
|
||||
return String(this.__wrapped__);
|
||||
return this.__wrapped__ + '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4323,7 +4336,7 @@
|
||||
lodash.prototype.valueOf = wrapperValueOf;
|
||||
|
||||
// add `Array` functions that return unwrapped values
|
||||
forEach(['join', 'pop', 'shift'], function(methodName) {
|
||||
each(['join', 'pop', 'shift'], function(methodName) {
|
||||
var func = arrayRef[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
return func.apply(this.__wrapped__, arguments);
|
||||
@@ -4331,7 +4344,7 @@
|
||||
});
|
||||
|
||||
// add `Array` functions that return the wrapped value
|
||||
forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
|
||||
each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
|
||||
var func = arrayRef[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
func.apply(this.__wrapped__, arguments);
|
||||
@@ -4340,7 +4353,7 @@
|
||||
});
|
||||
|
||||
// add `Array` functions that return new wrapped values
|
||||
forEach(['concat', 'slice', 'splice'], function(methodName) {
|
||||
each(['concat', 'slice', 'splice'], function(methodName) {
|
||||
var func = arrayRef[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
var result = func.apply(this.__wrapped__, arguments);
|
||||
@@ -4351,7 +4364,7 @@
|
||||
// avoid array-like object bugs with `Array#shift` and `Array#splice`
|
||||
// in Firefox < 10 and IE < 9
|
||||
if (hasObjectSpliceBug) {
|
||||
forEach(['shift', 'splice'], function(methodName) {
|
||||
each(['shift', 'splice'], function(methodName) {
|
||||
var func = lodash.prototype[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
var value = this.__wrapped__,
|
||||
@@ -4366,6 +4379,7 @@
|
||||
}
|
||||
|
||||
// add pseudo private property to be used and removed during the build process
|
||||
lodash._each = each;
|
||||
lodash._iteratorTemplate = iteratorTemplate;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user