mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-31 23:37:49 +00:00
Make remove compiling from _.merge, _.countBy, _.groupBy, _.pick, _.omit, and _.sortBy.
Former-commit-id: 52b245e69629e7a9fbe5f0dcbdfafabcd75d9dfc
This commit is contained in:
17
build.js
17
build.js
@@ -71,7 +71,7 @@
|
||||
'compact': [],
|
||||
'compose': [],
|
||||
'contains': [],
|
||||
'countBy': ['identity'],
|
||||
'countBy': ['forEach', 'identity'],
|
||||
'debounce': [],
|
||||
'defaults': ['isArguments'],
|
||||
'defer': [],
|
||||
@@ -88,7 +88,7 @@
|
||||
'forIn': ['identity', 'isArguments'],
|
||||
'forOwn': ['identity', 'isArguments'],
|
||||
'functions': ['isArguments', 'isFunction'],
|
||||
'groupBy': ['identity'],
|
||||
'groupBy': ['forEach', 'identity'],
|
||||
'has': [],
|
||||
'identity': [],
|
||||
'indexOf': ['sortedIndex'],
|
||||
@@ -120,16 +120,16 @@
|
||||
'map': ['identity'],
|
||||
'max': ['forEach'],
|
||||
'memoize': [],
|
||||
'merge': ['isArray', 'isPlainObject'],
|
||||
'merge': ['forOwn', 'isArray', 'isPlainObject'],
|
||||
'min': ['forEach'],
|
||||
'mixin': ['forEach', 'functions'],
|
||||
'noConflict': [],
|
||||
'object': [],
|
||||
'omit': ['indexOf', 'isArguments'],
|
||||
'omit': ['forIn', 'indexOf', 'isArguments'],
|
||||
'once': [],
|
||||
'pairs': [],
|
||||
'partial': ['isFunction'],
|
||||
'pick': [],
|
||||
'pick': ['forIn'],
|
||||
'pluck': [],
|
||||
'random': [],
|
||||
'range': [],
|
||||
@@ -141,7 +141,7 @@
|
||||
'shuffle': ['forEach'],
|
||||
'size': ['keys'],
|
||||
'some': ['identity'],
|
||||
'sortBy': ['identity'],
|
||||
'sortBy': ['forEach', 'identity'],
|
||||
'sortedIndex': ['identity'],
|
||||
'tap': ['mixin'],
|
||||
'template': ['escape'],
|
||||
@@ -1247,11 +1247,6 @@
|
||||
source = source.replace(reFunc, '$1' + getFunctionSource(lodash[methodName]) + ';\n');
|
||||
});
|
||||
|
||||
// replace `callee` in `_.merge` with `merge`
|
||||
source = source.replace(matchFunction(source, 'merge'), function(match) {
|
||||
return match.replace(/\bcallee\b/g, 'merge');
|
||||
});
|
||||
|
||||
if (isUnderscore) {
|
||||
// remove "compiled template cleanup" from `_.template`
|
||||
source = source.replace(/(?:\s*\/\/.*)*\n *source *=.+?isEvaluating.+?reEmptyStringLeading[\s\S]+?\);/, '');
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
'argsLength',
|
||||
'callback',
|
||||
'collection',
|
||||
'concat',
|
||||
'createCallback',
|
||||
'ctor',
|
||||
'hasOwnProperty',
|
||||
@@ -36,38 +35,22 @@
|
||||
'value',
|
||||
|
||||
// lesser used variables
|
||||
'accumulator',
|
||||
'args',
|
||||
'arrayLikeClasses',
|
||||
'ArrayProto',
|
||||
'bind',
|
||||
'callee',
|
||||
'className',
|
||||
'compareAscending',
|
||||
'forIn',
|
||||
'found',
|
||||
'funcs',
|
||||
'indexOf',
|
||||
'indicator',
|
||||
'isArguments',
|
||||
'isArr',
|
||||
'isArray',
|
||||
'isFunc',
|
||||
'isFunction',
|
||||
'isPlainObject',
|
||||
'methodName',
|
||||
'noaccum',
|
||||
'noop',
|
||||
'objectClass',
|
||||
'objectTypes',
|
||||
'pass',
|
||||
'properties',
|
||||
'property',
|
||||
'propsLength',
|
||||
'source',
|
||||
'stackA',
|
||||
'stackB',
|
||||
'stackLength',
|
||||
'target'
|
||||
];
|
||||
|
||||
@@ -310,15 +293,13 @@
|
||||
// minify internal properties used by 'compareAscending', `_.merge`, and `_.sortBy`
|
||||
(function() {
|
||||
var properties = ['criteria', 'index', 'value'],
|
||||
snippets = source.match(/( +)(?:function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
|
||||
snippets = source.match(/( +)function (?:compareAscending|merge|sortBy)\b[\s\S]+?\n\1}/g);
|
||||
|
||||
if (!snippets) {
|
||||
return;
|
||||
}
|
||||
snippets.forEach(function(snippet) {
|
||||
var modified = snippet,
|
||||
isCompilable = /(?:var merge|var sortBy)\b/.test(modified),
|
||||
isInlined = !/\bcreateIterator\b/.test(modified);
|
||||
var modified = snippet;
|
||||
|
||||
// minify properties
|
||||
properties.forEach(function(property, index) {
|
||||
@@ -326,32 +307,14 @@
|
||||
reDotProp = RegExp('\\.' + property + '\\b', 'g'),
|
||||
rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g');
|
||||
|
||||
if (isCompilable) {
|
||||
// add quotes around properties in the inlined `_.merge` and `_.sortBy`
|
||||
// of the mobile build so Closure Compiler won't mung them
|
||||
if (isInlined) {
|
||||
modified = modified
|
||||
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||
.replace(reDotProp, "['" + minNames[index] + "']")
|
||||
.replace(rePropColon, "$1'" + minNames[index] + "':");
|
||||
}
|
||||
else {
|
||||
modified = modified
|
||||
.replace(reBracketProp, '.' + minNames[index])
|
||||
.replace(reDotProp, '.' + minNames[index])
|
||||
.replace(rePropColon, '$1' + minNames[index] + ':');
|
||||
}
|
||||
}
|
||||
else {
|
||||
modified = modified
|
||||
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||
.replace(reDotProp, '.' + minNames[index])
|
||||
.replace(rePropColon, "$1'" + minNames[index] + "':")
|
||||
modified = modified
|
||||
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||
.replace(reDotProp, '.' + minNames[index])
|
||||
.replace(rePropColon, "$1'" + minNames[index] + "':")
|
||||
|
||||
// correct `value.source` in regexp branch of `_.clone`
|
||||
if (property == 'source') {
|
||||
modified = modified.replace("value['" + minNames[index] + "']", "value['source']");
|
||||
}
|
||||
// correct `value.source` in regexp branch of `_.clone`
|
||||
if (property == 'source') {
|
||||
modified = modified.replace("value['" + minNames[index] + "']", "value['source']");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
242
lodash.js
242
lodash.js
@@ -425,9 +425,8 @@
|
||||
);
|
||||
|
||||
/**
|
||||
* Reusable iterator options shared by
|
||||
* `countBy`, `every`, `filter`, `find`, `forEach`, `forIn`, `forOwn`, `groupBy`,
|
||||
* `map`, `reject`, `some`, and `sortBy`.
|
||||
* Reusable iterator options shared by `every`, `filter`,
|
||||
* `find`, `forEach`, `forIn`, `forOwn`, `map`, `reject`, and `some`.
|
||||
*/
|
||||
var baseIteratorOptions = {
|
||||
'args': 'collection, callback, thisArg',
|
||||
@@ -435,15 +434,6 @@
|
||||
'inLoop': 'if (callback(value, index, collection) === false) return result'
|
||||
};
|
||||
|
||||
/** Reusable iterator options for `countBy`, `groupBy`, and `sortBy` */
|
||||
var countByIteratorOptions = {
|
||||
'init': '{}',
|
||||
'top': 'callback = createCallback(callback, thisArg)',
|
||||
'inLoop':
|
||||
'var prop = callback(value, index, collection);\n' +
|
||||
'(hasOwnProperty.call(result, prop) ? result[prop]++ : result[prop] = 1)'
|
||||
};
|
||||
|
||||
/** Reusable iterator options for `every` and `some` */
|
||||
var everyIteratorOptions = {
|
||||
'init': 'true',
|
||||
@@ -480,7 +470,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
/** Reusable iterator options for `invoke`, `map`, `pluck`, and `sortBy` */
|
||||
/** Reusable iterator options for `invoke`, `map`, and `pluck` */
|
||||
var mapIteratorOptions = {
|
||||
'init': 'collection || []',
|
||||
'beforeLoop': {
|
||||
@@ -493,22 +483,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
/** Reusable iterator options for `omit` and `pick` */
|
||||
var omitIteratorOptions = {
|
||||
'useHas': false,
|
||||
'args': 'object, callback, thisArg',
|
||||
'init': '{}',
|
||||
'top':
|
||||
'var isFunc = typeof callback == \'function\';\n' +
|
||||
'if (isFunc) callback = createCallback(callback, thisArg);\n' +
|
||||
'else var props = concat.apply(ArrayProto, arguments)',
|
||||
'inLoop':
|
||||
'if (isFunc\n' +
|
||||
' ? !callback(value, index, object)\n' +
|
||||
' : indexOf(props, index) < 0\n' +
|
||||
') result[index] = value'
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
@@ -727,18 +701,15 @@
|
||||
}
|
||||
// create the function factory
|
||||
var factory = Function(
|
||||
'arrayLikeClasses, ArrayProto, bind, compareAscending, concat, createCallback, ' +
|
||||
'forIn, hasOwnProperty, indexOf, isArguments, isArray, isFunction, ' +
|
||||
'isPlainObject, objectClass, objectTypes, nativeKeys, propertyIsEnumerable, ' +
|
||||
'arrayLikeClasses, bind, createCallback, forIn, hasOwnProperty, isArguments, ' +
|
||||
'isFunction, objectClass, objectTypes, nativeKeys, propertyIsEnumerable, ' +
|
||||
'slice, stringClass, toString, undefined',
|
||||
'var callee = function(' + args + ') {\n' + iteratorTemplate(data) + '\n};\n' +
|
||||
'return callee'
|
||||
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
||||
);
|
||||
// return the compiled function
|
||||
return factory(
|
||||
arrayLikeClasses, ArrayProto, bind, compareAscending, concat, createCallback,
|
||||
forIn, hasOwnProperty, indexOf, isArguments, isArray, isFunction,
|
||||
isPlainObject, objectClass, objectTypes, nativeKeys, propertyIsEnumerable,
|
||||
arrayLikeClasses, bind, createCallback, forIn, hasOwnProperty, isArguments,
|
||||
isFunction, objectClass, objectTypes, nativeKeys, propertyIsEnumerable,
|
||||
slice, stringClass, toString
|
||||
);
|
||||
}
|
||||
@@ -1705,37 +1676,48 @@
|
||||
* _.merge(stooges, ages);
|
||||
* // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }]
|
||||
*/
|
||||
var merge = createIterator(extendIteratorOptions, {
|
||||
'args': 'object, source, indicator',
|
||||
'top':
|
||||
'var isArr, args = arguments, argsIndex = 0;\n' +
|
||||
'if (indicator == compareAscending) {\n' +
|
||||
' var argsLength = 2, stackA = args[3], stackB = args[4]\n' +
|
||||
'} else {\n' +
|
||||
' var argsLength = args.length, stackA = [], stackB = []\n' +
|
||||
'}\n' +
|
||||
'while (++argsIndex < argsLength) {\n' +
|
||||
' if (iteratee = args[argsIndex]) {',
|
||||
'inLoop':
|
||||
'if ((source = value) && ((isArr = isArray(source)) || isPlainObject(source))) {\n' +
|
||||
' var found = false, stackLength = stackA.length;\n' +
|
||||
' while (stackLength--) {\n' +
|
||||
' if (found = stackA[stackLength] == source) break\n' +
|
||||
' }\n' +
|
||||
' if (found) {\n' +
|
||||
' result[index] = stackB[stackLength]\n' +
|
||||
' } else {\n' +
|
||||
' stackA.push(source);\n' +
|
||||
' stackB.push(value = (value = result[index], isArr)\n' +
|
||||
' ? (isArray(value) ? value : [])\n' +
|
||||
' : (isPlainObject(value) ? value : {})\n' +
|
||||
' );\n' +
|
||||
' result[index] = callee(value, source, compareAscending, stackA, stackB)\n' +
|
||||
' }\n' +
|
||||
'} else if (source != null) {\n' +
|
||||
' result[index] = source\n' +
|
||||
'}'
|
||||
});
|
||||
function merge(object, source, indicator) {
|
||||
var args = arguments,
|
||||
index = 0,
|
||||
length = 2,
|
||||
stackA = args[3],
|
||||
stackB = args[4];
|
||||
|
||||
if (indicator != compareAscending) {
|
||||
length = args.length;
|
||||
stackA = [];
|
||||
stackB = [];
|
||||
}
|
||||
while (++index < length) {
|
||||
forOwn(args[index], function(source, key) {
|
||||
var isArr, value;
|
||||
if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
|
||||
var found = false,
|
||||
stackLength = stackA.length;
|
||||
|
||||
while (stackLength--) {
|
||||
if ((found = stackA[stackLength] == source)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
object[key] = stackB[stackLength];
|
||||
}
|
||||
else {
|
||||
stackA.push(source);
|
||||
stackB.push(value = (value = object[key], isArr)
|
||||
? (isArray(value) ? value : [])
|
||||
: (isPlainObject(value) ? value : {})
|
||||
);
|
||||
object[key] = merge(value, source, compareAscending, stackA, stackB);
|
||||
}
|
||||
} else if (source != null) {
|
||||
object[key] = source;
|
||||
}
|
||||
});
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shallow clone of `object` excluding the specified properties.
|
||||
@@ -1762,7 +1744,25 @@
|
||||
* });
|
||||
* // => { 'name': 'moe' }
|
||||
*/
|
||||
var omit = createIterator(omitIteratorOptions);
|
||||
function omit(object, callback, thisArg) {
|
||||
var isFunc = typeof callback == 'function',
|
||||
result = {};
|
||||
|
||||
if (isFunc) {
|
||||
callback = createCallback(callback, thisArg);
|
||||
} else {
|
||||
var props = concat.apply(ArrayProto, arguments);
|
||||
}
|
||||
forIn(object, function(value, key, object) {
|
||||
if (isFunc
|
||||
? !callback(value, key, object)
|
||||
: indexOf(props, key) < 0
|
||||
) {
|
||||
result[key] = value;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two dimensional array of the given object's key-value pairs,
|
||||
@@ -1809,22 +1809,29 @@
|
||||
* });
|
||||
* // => { 'name': 'moe' }
|
||||
*/
|
||||
var pick = createIterator(omitIteratorOptions, {
|
||||
'top':
|
||||
'if (typeof callback != \'function\') {\n' +
|
||||
' var index = 0,\n' +
|
||||
' props = concat.apply(ArrayProto, arguments),\n' +
|
||||
' length = props.length;\n' +
|
||||
' while (++index < length) {\n' +
|
||||
' var prop = props[index];\n' +
|
||||
' if (prop in object) result[prop] = object[prop]\n' +
|
||||
' }\n' +
|
||||
'} else {\n' +
|
||||
' callback = createCallback(callback, thisArg)',
|
||||
'inLoop':
|
||||
'if (callback(value, index, object)) result[index] = value',
|
||||
'bottom': '}'
|
||||
});
|
||||
function pick(object, callback, thisArg) {
|
||||
var result = {};
|
||||
if (typeof callback != 'function') {
|
||||
var index = 0,
|
||||
props = concat.apply(ArrayProto, arguments),
|
||||
length = props.length;
|
||||
|
||||
while (++index < length) {
|
||||
var prop = props[index];
|
||||
if (prop in object) {
|
||||
result[prop] = object[prop];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
callback = createCallback(callback, thisArg);
|
||||
forIn(object, function(value, key, object) {
|
||||
if (callback(value, key, object)) {
|
||||
result[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array composed of the own enumerable property values of `object`.
|
||||
@@ -1905,7 +1912,15 @@
|
||||
* _.countBy(['one', 'two', 'three'], 'length');
|
||||
* // => { '3': 2, '5': 1 }
|
||||
*/
|
||||
var countBy = createIterator(baseIteratorOptions, countByIteratorOptions);
|
||||
function countBy(collection, callback, thisArg) {
|
||||
var result = {};
|
||||
callback = createCallback(callback, thisArg);
|
||||
forEach(collection, function(value, key, collection) {
|
||||
key = callback(value, key, collection);
|
||||
(hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the `callback` returns a truthy value for **all** elements of a
|
||||
@@ -2023,11 +2038,15 @@
|
||||
* _.groupBy(['one', 'two', 'three'], 'length');
|
||||
* // => { '3': ['one', 'two'], '5': ['three'] }
|
||||
*/
|
||||
var groupBy = createIterator(baseIteratorOptions, countByIteratorOptions, {
|
||||
'inLoop':
|
||||
'var prop = callback(value, index, collection);\n' +
|
||||
'(hasOwnProperty.call(result, prop) ? result[prop] : result[prop] = []).push(value)'
|
||||
});
|
||||
function groupBy(collection, callback, thisArg) {
|
||||
var result = {};
|
||||
callback = createCallback(callback, thisArg);
|
||||
forEach(collection, function(value, key, collection) {
|
||||
key = callback(value, key, collection);
|
||||
(hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the method named by `methodName` on each element in the `collection`,
|
||||
@@ -2408,28 +2427,25 @@
|
||||
* _.sortBy(['larry', 'brendan', 'moe'], 'length');
|
||||
* // => ['moe', 'larry', 'brendan']
|
||||
*/
|
||||
var sortBy = createIterator(baseIteratorOptions, countByIteratorOptions, mapIteratorOptions, {
|
||||
'inLoop': {
|
||||
'array':
|
||||
'result[index] = {\n' +
|
||||
' criteria: callback(value, index, collection),\n' +
|
||||
' index: index,\n' +
|
||||
' value: value\n' +
|
||||
'}',
|
||||
'object':
|
||||
'result' + (isKeysFast ? '[ownIndex] = ' : '.push') + '({\n' +
|
||||
' criteria: callback(value, index, collection),\n' +
|
||||
' index: index,\n' +
|
||||
' value: value\n' +
|
||||
'})'
|
||||
},
|
||||
'bottom':
|
||||
'result.sort(compareAscending);\n' +
|
||||
'length = result.length;\n' +
|
||||
'while (length--) {\n' +
|
||||
' result[length] = result[length].value\n' +
|
||||
'}'
|
||||
});
|
||||
function sortBy(collection, callback, thisArg) {
|
||||
var result = [];
|
||||
callback = createCallback(callback, thisArg);
|
||||
|
||||
forEach(collection, function(value, index, collection) {
|
||||
result.push({
|
||||
'criteria': callback(value, index, collection),
|
||||
'index': index,
|
||||
'value': value
|
||||
});
|
||||
});
|
||||
|
||||
var length = result.length;
|
||||
result.sort(compareAscending);
|
||||
while (length--) {
|
||||
result[length] = result[length].value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the `collection`, to an array.
|
||||
|
||||
Reference in New Issue
Block a user