Add baseRest.

This commit is contained in:
John-David Dalton
2016-07-17 17:14:36 -07:00
parent 90d73143e1
commit ec4ae5978b

153
lodash.js
View File

@@ -3664,6 +3664,40 @@
return result;
}
/**
* The base implementation of `_.rest` which doesn't validate or coerce arguments.
*
* @private
* @param {Function} func The function to apply a rest parameter to.
* @param {number} [start=func.length-1] The start position of the rest parameter.
* @returns {Function} Returns the new function.
*/
function baseRest(func, start) {
start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
return function() {
var args = arguments,
index = -1,
length = nativeMax(args.length - start, 0),
array = Array(length);
while (++index < length) {
array[index] = args[start + index];
}
switch (start) {
case 0: return func.call(this, array);
case 1: return func.call(this, args[0], array);
case 2: return func.call(this, args[0], args[1], array);
}
var otherArgs = Array(start + 1);
index = -1;
while (++index < start) {
otherArgs[index] = args[index];
}
otherArgs[start] = array;
return apply(func, this, otherArgs);
};
}
/**
* The base implementation of `_.set`.
*
@@ -4487,7 +4521,7 @@
* @returns {Function} Returns the new assigner function.
*/
function createAssigner(assigner) {
return rest(function(object, sources) {
return baseRest(function(object, sources) {
var index = -1,
length = sources.length,
customizer = length > 1 ? sources[length - 1] : undefined,
@@ -4724,7 +4758,7 @@
* @returns {Function} Returns the new flow function.
*/
function createFlow(fromRight) {
return rest(function(funcs) {
return baseRest(function(funcs) {
funcs = baseFlatten(funcs, 1);
var length = funcs.length,
@@ -4909,12 +4943,12 @@
* @returns {Function} Returns the new over function.
*/
function createOver(arrayFunc) {
return rest(function(iteratees) {
return baseRest(function(iteratees) {
iteratees = (iteratees.length == 1 && isArray(iteratees[0]))
? arrayMap(iteratees[0], baseUnary(getIteratee()))
: arrayMap(baseFlatten(iteratees, 1), baseUnary(getIteratee()));
return rest(function(args) {
return baseRest(function(args) {
var thisArg = this;
return arrayFunc(iteratees, function(iteratee) {
return apply(iteratee, thisArg, args);
@@ -6406,7 +6440,7 @@
* _.difference([2, 1], [2, 3]);
* // => [1]
*/
var difference = rest(function(array, values) {
var difference = baseRest(function(array, values) {
return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
: [];
@@ -6437,7 +6471,7 @@
* _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
var differenceBy = rest(function(array, values) {
var differenceBy = baseRest(function(array, values) {
var iteratee = last(values);
if (isArrayLikeObject(iteratee)) {
iteratee = undefined;
@@ -6470,7 +6504,7 @@
* _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
* // => [{ 'x': 2, 'y': 1 }]
*/
var differenceWith = rest(function(array, values) {
var differenceWith = baseRest(function(array, values) {
var comparator = last(values);
if (isArrayLikeObject(comparator)) {
comparator = undefined;
@@ -6958,7 +6992,7 @@
* _.intersection([2, 1], [2, 3]);
* // => [2]
*/
var intersection = rest(function(arrays) {
var intersection = baseRest(function(arrays) {
var mapped = arrayMap(arrays, castArrayLikeObject);
return (mapped.length && mapped[0] === arrays[0])
? baseIntersection(mapped)
@@ -6987,7 +7021,7 @@
* _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }]
*/
var intersectionBy = rest(function(arrays) {
var intersectionBy = baseRest(function(arrays) {
var iteratee = last(arrays),
mapped = arrayMap(arrays, castArrayLikeObject);
@@ -7022,7 +7056,7 @@
* _.intersectionWith(objects, others, _.isEqual);
* // => [{ 'x': 1, 'y': 2 }]
*/
var intersectionWith = rest(function(arrays) {
var intersectionWith = baseRest(function(arrays) {
var comparator = last(arrays),
mapped = arrayMap(arrays, castArrayLikeObject);
@@ -7168,7 +7202,7 @@
* console.log(array);
* // => ['b', 'b']
*/
var pull = rest(pullAll);
var pull = baseRest(pullAll);
/**
* This method is like `_.pull` except that it accepts an array of values to remove.
@@ -7279,7 +7313,7 @@
* console.log(pulled);
* // => ['b', 'd']
*/
var pullAt = rest(function(array, indexes) {
var pullAt = baseRest(function(array, indexes) {
indexes = baseFlatten(indexes, 1);
var length = array ? array.length : 0,
@@ -7787,7 +7821,7 @@
* _.union([2], [1, 2]);
* // => [2, 1]
*/
var union = rest(function(arrays) {
var union = baseRest(function(arrays) {
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
});
@@ -7815,7 +7849,7 @@
* _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
var unionBy = rest(function(arrays) {
var unionBy = baseRest(function(arrays) {
var iteratee = last(arrays);
if (isArrayLikeObject(iteratee)) {
iteratee = undefined;
@@ -7844,7 +7878,7 @@
* _.unionWith(objects, others, _.isEqual);
* // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
*/
var unionWith = rest(function(arrays) {
var unionWith = baseRest(function(arrays) {
var comparator = last(arrays);
if (isArrayLikeObject(comparator)) {
comparator = undefined;
@@ -8017,7 +8051,7 @@
* _.without([2, 1, 2, 3], 1, 2);
* // => [3]
*/
var without = rest(function(array, values) {
var without = baseRest(function(array, values) {
return isArrayLikeObject(array)
? baseDifference(array, values)
: [];
@@ -8041,7 +8075,7 @@
* _.xor([2, 1], [2, 3]);
* // => [1, 3]
*/
var xor = rest(function(arrays) {
var xor = baseRest(function(arrays) {
return baseXor(arrayFilter(arrays, isArrayLikeObject));
});
@@ -8068,7 +8102,7 @@
* _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
var xorBy = rest(function(arrays) {
var xorBy = baseRest(function(arrays) {
var iteratee = last(arrays);
if (isArrayLikeObject(iteratee)) {
iteratee = undefined;
@@ -8096,7 +8130,7 @@
* _.xorWith(objects, others, _.isEqual);
* // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
*/
var xorWith = rest(function(arrays) {
var xorWith = baseRest(function(arrays) {
var comparator = last(arrays);
if (isArrayLikeObject(comparator)) {
comparator = undefined;
@@ -8120,7 +8154,7 @@
* _.zip(['a', 'b'], [1, 2], [true, false]);
* // => [['a', 1, true], ['b', 2, false]]
*/
var zip = rest(unzip);
var zip = baseRest(unzip);
/**
* This method is like `_.fromPairs` except that it accepts two arrays,
@@ -8180,7 +8214,7 @@
* });
* // => [111, 222]
*/
var zipWith = rest(function(arrays) {
var zipWith = baseRest(function(arrays) {
var length = arrays.length,
iteratee = length > 1 ? arrays[length - 1] : undefined;
@@ -8296,7 +8330,7 @@
* _(object).at(['a[0].b.c', 'a[1]']).value();
* // => [3, 4]
*/
var wrapperAt = rest(function(paths) {
var wrapperAt = baseRest(function(paths) {
paths = baseFlatten(paths, 1);
var length = paths.length,
start = length ? paths[0] : 0,
@@ -8950,7 +8984,7 @@
* _.invokeMap([123, 456], String.prototype.split, '');
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
var invokeMap = rest(function(collection, path, args) {
var invokeMap = baseRest(function(collection, path, args) {
var index = -1,
isFunc = typeof path == 'function',
isProp = isKey(path),
@@ -9439,7 +9473,7 @@
* });
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
*/
var sortBy = rest(function(collection, iteratees) {
var sortBy = baseRest(function(collection, iteratees) {
if (collection == null) {
return [];
}
@@ -9604,7 +9638,7 @@
* bound('hi');
* // => 'hi fred!'
*/
var bind = rest(function(func, thisArg, partials) {
var bind = baseRest(function(func, thisArg, partials) {
var bitmask = BIND_FLAG;
if (partials.length) {
var holders = replaceHolders(partials, getHolder(bind));
@@ -9658,7 +9692,7 @@
* bound('hi');
* // => 'hiya fred!'
*/
var bindKey = rest(function(object, key, partials) {
var bindKey = baseRest(function(object, key, partials) {
var bitmask = BIND_FLAG | BIND_KEY_FLAG;
if (partials.length) {
var holders = replaceHolders(partials, getHolder(bindKey));
@@ -9950,7 +9984,7 @@
* }, 'deferred');
* // => Logs 'deferred' after one or more milliseconds.
*/
var defer = rest(function(func, args) {
var defer = baseRest(function(func, args) {
return baseDelay(func, 1, args);
});
@@ -9973,7 +10007,7 @@
* }, 1000, 'later');
* // => Logs 'later' after one second.
*/
var delay = rest(function(func, wait, args) {
var delay = baseRest(function(func, wait, args) {
return baseDelay(func, toNumber(wait) || 0, args);
});
@@ -10148,13 +10182,13 @@
* func(10, 5);
* // => [100, 10]
*/
var overArgs = rest(function(func, transforms) {
var overArgs = baseRest(function(func, transforms) {
transforms = (transforms.length == 1 && isArray(transforms[0]))
? arrayMap(transforms[0], baseUnary(getIteratee()))
: arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
var funcsLength = transforms.length;
return rest(function(args) {
return baseRest(function(args) {
var index = -1,
length = nativeMin(args.length, funcsLength);
@@ -10198,7 +10232,7 @@
* greetFred('hi');
* // => 'hi fred'
*/
var partial = rest(function(func, partials) {
var partial = baseRest(function(func, partials) {
var holders = replaceHolders(partials, getHolder(partial));
return createWrap(func, PARTIAL_FLAG, undefined, partials, holders);
});
@@ -10235,7 +10269,7 @@
* sayHelloTo('fred');
* // => 'hello fred'
*/
var partialRight = rest(function(func, partials) {
var partialRight = baseRest(function(func, partials) {
var holders = replaceHolders(partials, getHolder(partialRight));
return createWrap(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders);
});
@@ -10262,7 +10296,7 @@
* rearged('b', 'c', 'a')
* // => ['a', 'b', 'c']
*/
var rearg = rest(function(func, indexes) {
var rearg = baseRest(function(func, indexes) {
return createWrap(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1));
});
@@ -10295,29 +10329,8 @@
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0);
return function() {
var args = arguments,
index = -1,
length = nativeMax(args.length - start, 0),
array = Array(length);
while (++index < length) {
array[index] = args[start + index];
}
switch (start) {
case 0: return func.call(this, array);
case 1: return func.call(this, args[0], array);
case 2: return func.call(this, args[0], args[1], array);
}
var otherArgs = Array(start + 1);
index = -1;
while (++index < start) {
otherArgs[index] = args[index];
}
otherArgs[start] = array;
return apply(func, this, otherArgs);
};
start = start === undefined ? start : toInteger(start);
return baseRest(func, start);
}
/**
@@ -10359,7 +10372,7 @@
throw new TypeError(FUNC_ERROR_TEXT);
}
start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
return rest(function(args) {
return baseRest(function(args) {
var array = args[start],
otherArgs = castSlice(args, 0, start);
@@ -12240,7 +12253,7 @@
* _.at(object, ['a[0].b.c', 'a[1]']);
* // => [3, 4]
*/
var at = rest(function(object, paths) {
var at = baseRest(function(object, paths) {
return baseAt(object, baseFlatten(paths, 1));
});
@@ -12304,7 +12317,7 @@
* _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
* // => { 'a': 1, 'b': 2 }
*/
var defaults = rest(function(args) {
var defaults = baseRest(function(args) {
args.push(undefined, assignInDefaults);
return apply(assignInWith, undefined, args);
});
@@ -12328,7 +12341,7 @@
* _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
* // => { 'a': { 'b': 2, 'c': 3 } }
*/
var defaultsDeep = rest(function(args) {
var defaultsDeep = baseRest(function(args) {
args.push(undefined, mergeDefaults);
return apply(mergeWith, undefined, args);
});
@@ -12758,7 +12771,7 @@
* _.invoke(object, 'a[0].b.c.slice', 1, 3);
* // => [2, 3]
*/
var invoke = rest(baseInvoke);
var invoke = baseRest(baseInvoke);
/**
* Creates an array of the own enumerable property names of `object`.
@@ -13009,7 +13022,7 @@
* _.omit(object, ['a', 'c']);
* // => { 'b': '2' }
*/
var omit = rest(function(object, props) {
var omit = baseRest(function(object, props) {
if (object == null) {
return {};
}
@@ -13061,7 +13074,7 @@
* _.pick(object, ['a', 'c']);
* // => { 'a': 1, 'c': 3 }
*/
var pick = rest(function(object, props) {
var pick = baseRest(function(object, props) {
return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey));
});
@@ -14741,7 +14754,7 @@
* elements = [];
* }
*/
var attempt = rest(function(func, args) {
var attempt = baseRest(function(func, args) {
try {
return apply(func, undefined, args);
} catch (e) {
@@ -14775,7 +14788,7 @@
* jQuery(element).on('click', view.click);
* // => Logs 'clicked docs' when clicked.
*/
var bindAll = rest(function(object, methodNames) {
var bindAll = baseRest(function(object, methodNames) {
arrayEach(baseFlatten(methodNames, 1), function(key) {
key = toKey(key);
object[key] = bind(object[key], object);
@@ -14823,7 +14836,7 @@
return [toIteratee(pair[0]), pair[1]];
});
return rest(function(args) {
return baseRest(function(args) {
var index = -1;
while (++index < length) {
var pair = pairs[index];
@@ -15101,7 +15114,7 @@
* _.map(objects, _.method(['a', 'b']));
* // => [2, 1]
*/
var method = rest(function(path, args) {
var method = baseRest(function(path, args) {
return function(object) {
return baseInvoke(object, path, args);
};
@@ -15130,7 +15143,7 @@
* _.map([['a', '2'], ['c', '0']], _.methodOf(object));
* // => [2, 0]
*/
var methodOf = rest(function(object, args) {
var methodOf = baseRest(function(object, args) {
return function(path) {
return baseInvoke(object, path, args);
};
@@ -15266,7 +15279,7 @@
*/
function nthArg(n) {
n = toInteger(n);
return rest(function(args) {
return baseRest(function(args) {
return baseNth(args, n);
});
}
@@ -16420,7 +16433,7 @@
return this.reverse().find(predicate);
};
LazyWrapper.prototype.invokeMap = rest(function(path, args) {
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
if (typeof path == 'function') {
return new LazyWrapper(this);
}