Allow _.first, _.last, _.initial, and _.rest to accept callback and thisArg arguments. [closes #155]

Former-commit-id: b921ae0ccc188c5544480f397216ce3b2479989e
This commit is contained in:
John-David Dalton
2013-01-13 14:58:53 -08:00
parent 9867d4bdc3
commit e5e914282f
6 changed files with 637 additions and 264 deletions

View File

@@ -635,7 +635,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
* @example
*
* (function() { return _.isArguments(arguments); })(1, 2, 3);
@@ -752,7 +752,7 @@
*
* @private
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
// avoid non-objects and false positives for `arguments` objects
@@ -960,7 +960,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
* @example
*
* (function() { return _.isArray(arguments); })();
@@ -976,13 +976,13 @@
};
/**
* Checks if `value` is a boolean (`true` or `false`) value.
* Checks if `value` is a boolean value.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
* @example
*
* _.isBoolean(null);
@@ -999,7 +999,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
* @example
*
* _.isDate(new Date);
@@ -1016,7 +1016,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
* @example
*
* _.isElement(document.body);
@@ -1035,7 +1035,7 @@
* @memberOf _
* @category Objects
* @param {Array|Object|String} value The value to inspect.
* @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
* @example
*
* _.isEmpty([1, 2, 3]);
@@ -1073,7 +1073,7 @@
* @param {Mixed} b The other value to compare.
* @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
* @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
* @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
* @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
* @example
*
* var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
@@ -1212,7 +1212,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
* @example
*
* _.isFinite(-101);
@@ -1241,7 +1241,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
@@ -1265,7 +1265,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
@@ -1295,7 +1295,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
@@ -1323,7 +1323,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
@@ -1343,7 +1343,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
* @example
*
* _.isNumber(8.4 * 5);
@@ -1360,7 +1360,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
* @example
*
* _.isRegExp(/moe/);
@@ -1377,7 +1377,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
* @example
*
* _.isString('moe');
@@ -1394,7 +1394,7 @@
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
* @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
@@ -1804,7 +1804,7 @@
/**
* Invokes the method named by `methodName` on each element in the `collection`,
* returning an array of the results of each invoked method. Additional arguments
* will be passed to each invoked method. If `methodName` is a function it will
* will be passed to each invoked method. If `methodName` is a function, it will
* be invoked for, and `this` bound to, each element in the `collection`.
*
* @static
@@ -2350,30 +2350,51 @@
}
/**
* Gets the first element of the `array`. Pass `n` to return the first `n`
* elements of the `array`.
* Gets the first element of the `array`. If a number `n` is passed, the first
* `n` elements of the `array` are returned. If a `callback` function is passed,
* the first elements the `callback` returns truthy for are returned. The `callback`
* is bound to `thisArg` and invoked with three arguments; (value, index, array).
*
* @static
* @memberOf _
* @alias head, take
* @category Arrays
* @param {Array} array The array to query.
* @param {Number} [n] The number of elements to return.
* @param- {Object} [guard] Internally used to allow this method to work with
* others like `_.map` without using their callback `index` argument for `n`.
* @returns {Mixed} Returns the first element, or an array of the first `n`
* elements, of `array`.
* @param {Function|Number} [callback|n] The function called per element or
* the number of elements to return.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the first element(s) of `array`.
* @example
*
* _.first([5, 4, 3, 2, 1]);
* // => 5
* _.first([1, 2, 3]);
* // => 1
*
* _.first([1, 2, 3], 2);
* // => [1, 2]
*
* _.first([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [1, 2]
*/
function first(array, n, guard) {
function first(array, callback, thisArg) {
if (array) {
var length = array.length;
return (n == null || guard)
? array[0]
: slice(array, 0, nativeMin(nativeMax(0, n), length));
var n = 0,
length = array.length;
if (typeof callback == 'function') {
var index = -1;
callback = createCallback(callback, thisArg);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array[0];
}
}
return slice(array, 0, nativeMin(nativeMax(0, n), length));
}
}
@@ -2456,28 +2477,49 @@
}
/**
* Gets all but the last element of `array`. Pass `n` to exclude the last `n`
* elements from the result.
* Gets all but the last element of `array`. If a number `n` is passed, the
* last `n` elements are excluded from the result. If a `callback` function
* is passed, the last elements the `callback` returns truthy for are excluded
* from the result. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Number} [n=1] The number of elements to exclude.
* @param- {Object} [guard] Internally used to allow this method to work with
* others like `_.map` without using their callback `index` argument for `n`.
* @returns {Array} Returns all but the last element, or `n` elements, of `array`.
* @param {Function|Number} [callback|n=1] The function called per element or
* the number of elements to exclude.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.initial([3, 2, 1]);
* // => [3, 2]
* _.initial([1, 2, 3]);
* // => [1, 2]
*
* _.initial([1, 2, 3], 2);
* // => [1]
*
* _.initial([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [1]
*/
function initial(array, n, guard) {
function initial(array, callback, thisArg) {
if (!array) {
return [];
}
var length = array.length;
n = n == null || guard ? 1 : n || 0;
var n = 0,
length = array.length;
if (typeof callback == 'function') {
var index = length;
callback = createCallback(callback, thisArg);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : callback || n;
}
return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
}
@@ -2520,27 +2562,50 @@
}
/**
* Gets the last element of the `array`. Pass `n` to return the last `n`
* elements of the `array`.
* Gets the last element of the `array`. If a number `n` is passed, the last
* `n` elements of the `array` are returned. If a `callback` function is passed,
* the last elements the `callback` returns truthy for are returned. The `callback`
* is bound to `thisArg` and invoked with three arguments; (value, index, array).
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Number} [n] The number of elements to return.
* @param- {Object} [guard] Internally used to allow this method to work with
* others like `_.map` without using their callback `index` argument for `n`.
* @returns {Mixed} Returns the last element, or an array of the last `n`
* elements, of `array`.
* @param {Function|Number} [callback|n] The function called per element or
* the number of elements to return.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the last element(s) of `array`.
* @example
*
* _.last([3, 2, 1]);
* // => 1
* _.last([1, 2, 3]);
* // => 3
*
* _.last([1, 2, 3], 2);
* // => [2, 3]
*
* _.last([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [2, 3]
*/
function last(array, n, guard) {
function last(array, callback, thisArg) {
if (array) {
var length = array.length;
return (n == null || guard) ? array[length - 1] : slice(array, nativeMax(0, length - n));
var n = 0,
length = array.length;
if (typeof callback == 'function') {
var index = length;
callback = createCallback(callback, thisArg);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array[length - 1];
}
}
return slice(array, nativeMax(0, length - n));
}
}
@@ -2661,25 +2726,48 @@
}
/**
* The opposite of `_.initial`, this method gets all but the first value of
* `array`. Pass `n` to exclude the first `n` values from the result.
* The opposite of `_.initial`, this method gets all but the first value of `array`.
* If a number `n` is passed, the first `n` values are excluded from the result.
* If a `callback` function is passed, the first elements the `callback` returns
* truthy for are excluded from the result. The `callback` is bound to `thisArg`
* and invoked with three arguments; (value, index, array).
*
* @static
* @memberOf _
* @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
* @param {Number} [n=1] The number of elements to exclude.
* @param- {Object} [guard] Internally used to allow this method to work with
* others like `_.map` without using their callback `index` argument for `n`.
* @returns {Array} Returns all but the first element, or `n` elements, of `array`.
* @param {Function|Number} [callback|n=1] The function called per element or
* the number of elements to exclude.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.rest([3, 2, 1]);
* // => [2, 1]
* _.rest([1, 2, 3]);
* // => [2, 3]
*
* _.rest([1, 2, 3], 2);
* // => [3]
*
* _.rest([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [3]
*/
function rest(array, n, guard) {
return slice(array, (n == null || guard) ? 1 : nativeMax(0, n));
function rest(array, callback, thisArg) {
if (typeof callback == 'function') {
var n = 0,
index = -1,
length = array ? array.length : 0;
callback = createCallback(callback, thisArg);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
}
return slice(array, n);
}
/**
@@ -3362,7 +3450,7 @@
}
/**
* Resolves the value of `property` on `object`. If `property` is a function
* Resolves the value of `property` on `object`. If `property` is a function,
* it will be invoked and its result returned, else the property value is
* returned. If `object` is falsey, then `null` is returned.
*