From d58549ce0b26c2b3b0696871eaff290acd78d702 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 24 Mar 2015 16:44:49 -0700 Subject: [PATCH] Bump to v3.6.0. --- README.md | 14 +- array/difference.js | 28 +- array/dropRightWhile.js | 14 +- array/dropWhile.js | 15 +- array/fill.js | 13 + array/findIndex.js | 17 +- array/findLastIndex.js | 13 +- array/flatten.js | 6 +- array/flattenDeep.js | 4 +- array/indexOf.js | 7 +- array/intersection.js | 7 +- array/pull.js | 8 +- array/pullAt.js | 33 +- array/remove.js | 2 +- array/sortedIndex.js | 14 +- array/sortedLastIndex.js | 10 +- array/takeRightWhile.js | 14 +- array/takeWhile.js | 15 +- array/union.js | 16 +- array/uniq.js | 13 +- array/without.js | 19 +- array/xor.js | 5 +- array/zip.js | 13 +- array/zipObject.js | 10 +- chain/thru.js | 7 +- collection/at.js | 11 +- collection/countBy.js | 6 +- collection/every.js | 8 +- collection/filter.js | 2 +- collection/find.js | 18 +- collection/findLast.js | 10 +- collection/forEach.js | 11 +- collection/forEachRight.js | 11 +- collection/groupBy.js | 6 +- collection/includes.js | 17 +- collection/indexBy.js | 6 +- collection/invoke.js | 20 +- collection/map.js | 12 +- collection/partition.js | 2 +- collection/reduce.js | 13 +- collection/reduceRight.js | 9 +- collection/shuffle.js | 5 +- collection/some.js | 8 +- collection/sortBy.js | 6 +- collection/sortByAll.js | 21 +- function.js | 1 + function/ary.js | 2 +- function/bind.js | 18 +- function/bindAll.js | 29 +- function/bindKey.js | 18 +- function/curry.js | 12 +- function/curryRight.js | 12 +- function/defer.js | 9 +- function/delay.js | 9 +- function/flow.js | 4 +- function/flowRight.js | 4 +- function/memoize.js | 6 +- function/once.js | 2 +- function/partial.js | 13 +- function/partialRight.js | 13 +- function/rearg.js | 12 +- function/restParam.js | 58 + function/spread.js | 15 +- index.js | 1800 +++++++++++-------- internal/arrayEach.js | 2 +- internal/arrayEachRight.js | 2 +- internal/arrayEvery.js | 2 +- internal/arrayFilter.js | 2 +- internal/arrayMap.js | 2 +- internal/arrayReduce.js | 2 +- internal/arrayReduceRight.js | 2 +- internal/arraySome.js | 2 +- internal/arraySum.js | 18 + internal/baseBindAll.js | 26 - internal/baseCallback.js | 9 +- internal/baseClone.js | 5 +- internal/baseDelay.js | 8 +- internal/baseEach.js | 19 +- internal/baseEachRight.js | 17 +- internal/baseEvery.js | 2 +- internal/baseFilter.js | 2 +- internal/baseFindIndex.js | 23 + internal/baseFlatten.js | 7 +- internal/baseFor.js | 17 +- internal/baseForRight.js | 16 +- internal/baseInvoke.js | 28 - internal/baseIsEqual.js | 6 +- internal/baseIsEqualDeep.js | 36 +- internal/baseIsMatch.js | 27 +- internal/baseMap.js | 2 +- internal/baseMatches.js | 18 +- internal/baseMatchesProperty.js | 6 +- internal/baseMergeDeep.js | 2 +- internal/basePullAt.js | 35 - internal/baseReduce.js | 2 +- internal/baseSome.js | 2 +- internal/baseSum.js | 20 + internal/baseWhile.js | 24 + internal/baseWrapperValue.js | 2 +- internal/binaryIndex.js | 3 +- internal/binaryIndexBy.js | 3 +- internal/createAggregator.js | 3 + internal/createAssigner.js | 2 + internal/createBaseEach.js | 30 + internal/createBaseFor.js | 27 + internal/createComposer.js | 39 - internal/createCurry.js | 23 + internal/createExtremum.js | 2 +- internal/createFind.js | 25 + internal/createFindIndex.js | 21 + internal/createFindKey.js | 18 + internal/createFlow.js | 64 + internal/createForEach.js | 20 + internal/createForIn.js | 20 + internal/createForOwn.js | 19 + internal/createHybridWrapper.js | 13 +- internal/createPadDir.js | 18 + internal/{createPad.js => createPadding.js} | 9 +- internal/createPartial.js | 20 + internal/createReduce.js | 22 + internal/createSortedIndex.js | 20 + internal/createWrapper.js | 4 +- internal/equalArrays.js | 14 +- internal/equalObjects.js | 18 +- internal/extremumBy.js | 2 +- internal/getFuncName.js | 37 + internal/indexOfNaN.js | 1 - internal/isBindable.js | 38 - internal/isIndex.js | 5 +- internal/isLaziable.js | 17 + internal/isLength.js | 9 +- internal/isObjectLike.js | 2 +- internal/mergeData.js | 28 +- internal/realNames.js | 4 + internal/shimIsPlainObject.js | 5 +- lang/clone.js | 6 +- lang/cloneDeep.js | 6 +- lang/isArguments.js | 7 +- lang/isArray.js | 7 +- lang/isBoolean.js | 7 +- lang/isDate.js | 7 +- lang/isElement.js | 11 +- lang/isEqual.js | 2 +- lang/isError.js | 7 +- lang/isFinite.js | 4 +- lang/isFunction.js | 5 +- lang/isMatch.js | 21 +- lang/isNaN.js | 5 +- lang/isNative.js | 7 +- lang/isNumber.js | 7 +- lang/isObject.js | 6 +- lang/isPlainObject.js | 5 +- lang/isRegExp.js | 5 +- lang/isString.js | 7 +- lang/isTypedArray.js | 7 +- math/max.js | 10 +- math/min.js | 10 +- math/sum.js | 47 +- object/assign.js | 2 +- object/defaults.js | 12 +- object/findKey.js | 14 +- object/findLastKey.js | 10 +- object/forIn.js | 12 +- object/forInRight.js | 8 +- object/forOwn.js | 11 +- object/forOwnRight.js | 10 +- object/mapValues.js | 2 +- object/merge.js | 2 +- object/omit.js | 15 +- object/pick.js | 15 +- object/transform.js | 2 +- package.json | 2 +- string/camelCase.js | 3 +- string/deburr.js | 12 +- string/escape.js | 5 +- string/escapeRegExp.js | 12 +- string/kebabCase.js | 4 +- string/pad.js | 9 +- string/padLeft.js | 13 +- string/padRight.js | 13 +- string/parseInt.js | 4 +- string/snakeCase.js | 3 +- string/startCase.js | 4 +- string/template.js | 10 +- string/trim.js | 2 +- string/trunc.js | 2 +- support.js | 7 +- utility/attempt.js | 16 +- utility/matchesProperty.js | 5 +- utility/mixin.js | 15 +- utility/property.js | 2 +- utility/propertyOf.js | 2 +- 192 files changed, 2218 insertions(+), 1804 deletions(-) create mode 100644 function/restParam.js create mode 100644 internal/arraySum.js delete mode 100644 internal/baseBindAll.js create mode 100644 internal/baseFindIndex.js delete mode 100644 internal/baseInvoke.js delete mode 100644 internal/basePullAt.js create mode 100644 internal/baseSum.js create mode 100644 internal/baseWhile.js create mode 100644 internal/createBaseEach.js create mode 100644 internal/createBaseFor.js delete mode 100644 internal/createComposer.js create mode 100644 internal/createCurry.js create mode 100644 internal/createFind.js create mode 100644 internal/createFindIndex.js create mode 100644 internal/createFindKey.js create mode 100644 internal/createFlow.js create mode 100644 internal/createForEach.js create mode 100644 internal/createForIn.js create mode 100644 internal/createForOwn.js create mode 100644 internal/createPadDir.js rename internal/{createPad.js => createPadding.js} (74%) create mode 100644 internal/createPartial.js create mode 100644 internal/createReduce.js create mode 100644 internal/createSortedIndex.js create mode 100644 internal/getFuncName.js delete mode 100644 internal/isBindable.js create mode 100644 internal/isLaziable.js create mode 100644 internal/realNames.js diff --git a/README.md b/README.md index b44492ce3..9838613f8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# lodash v3.5.0 +# lodash v3.6.0 The [modern build](https://github.com/lodash/lodash/wiki/Build-Differences) of [lodash](https://lodash.com/) exported as [Node.js](http://nodejs.org/)/[io.js](https://iojs.org/) modules. @@ -28,7 +28,7 @@ var array = require('lodash/array'); var chunk = require('lodash/array/chunk'); ``` -See the [package source](https://github.com/lodash/lodash/tree/3.5.0-npm) for more details. +See the [package source](https://github.com/lodash/lodash/tree/3.6.0-npm) for more details. **Note:**
Don’t assign values to the [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL.
@@ -39,8 +39,8 @@ Install [n_](https://www.npmjs.com/package/n_) for a REPL that includes lodash b lodash is also available in a variety of other builds & module formats. * npm packages for [modern](https://www.npmjs.com/package/lodash), [compatibility](https://www.npmjs.com/package/lodash-compat), & [per method](https://www.npmjs.com/browse/keyword/lodash-modularized) builds - * AMD modules for [modern](https://github.com/lodash/lodash/tree/3.5.0-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.5.0-amd) builds - * ES modules for the [modern](https://github.com/lodash/lodash/tree/3.5.0-es) build + * AMD modules for [modern](https://github.com/lodash/lodash/tree/3.6.0-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.6.0-amd) builds + * ES modules for the [modern](https://github.com/lodash/lodash/tree/3.6.0-es) build ## Further Reading @@ -51,7 +51,7 @@ lodash is also available in a variety of other builds & module formats. * [Roadmap](https://github.com/lodash/lodash/wiki/Roadmap) * [More Resources](https://github.com/lodash/lodash/wiki/Resources) -## Features *not* in Underscore +## Features * ~100% [code coverage](https://coveralls.io/r/lodash) * Follows [semantic versioning](http://semver.org/) for releases @@ -85,10 +85,10 @@ lodash is also available in a variety of other builds & module formats. * [_.parseInt](https://lodash.com/docs#parseInt) for consistent cross-environment behavior * [_.pull](https://lodash.com/docs#pull), [_.pullAt](https://lodash.com/docs#pullAt), & [_.remove](https://lodash.com/docs#remove) for mutating arrays * [_.random](https://lodash.com/docs#random) supports returning floating-point numbers + * [_.restParam](https://lodash.com/docs#restParam) & [_.spread](https://lodash.com/docs#spread) for applying rest parameters & spreading arguments to functions * [_.runInContext](https://lodash.com/docs#runInContext) for collisionless mixins & easier mocking * [_.slice](https://lodash.com/docs#slice) for creating subsets of array-like values * [_.sortByAll](https://lodash.com/docs#sortByAll) & [_.sortByOrder](https://lodash.com/docs#sortByOrder) for sorting by multiple properties & orders - * [_.spread](https://lodash.com/docs#spread) for creating a function to spread an array of arguments to another * [_.sum](https://lodash.com/docs#sum) to get the sum of values * [_.support](https://lodash.com/docs#support) for flagging environment features * [_.template](https://lodash.com/docs#template) supports [*“imports”*](https://lodash.com/docs#templateSettings-imports) options & [ES template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) @@ -112,5 +112,5 @@ lodash is also available in a variety of other builds & module formats. ## Support -Tested in Chrome 40-41, Firefox 35-36, IE 6-11, Opera 26-27, Safari 5-8, io.js 1.5.0, Node.js 0.8.28, 0.10.36, & 0.12.0, PhantomJS 1.9.8, RingoJS 0.11, & Rhino 1.7RC5. +Tested in Chrome 40-41, Firefox 35-36, IE 6-11, Opera 27-28, Safari 5-8, io.js 1.6.2, Node.js 0.8.28, 0.10.36, & 0.12.0, PhantomJS 1.9.8, RingoJS 0.11, & Rhino 1.7RC5. Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available. Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. diff --git a/array/difference.js b/array/difference.js index d05774e2c..277b836e6 100644 --- a/array/difference.js +++ b/array/difference.js @@ -1,16 +1,16 @@ var baseDifference = require('../internal/baseDifference'), baseFlatten = require('../internal/baseFlatten'), isArguments = require('../lang/isArguments'), - isArray = require('../lang/isArray'); + isArray = require('../lang/isArray'), + restParam = require('../function/restParam'); /** * Creates an array excluding all values of the provided arrays using * `SameValueZero` for equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -23,18 +23,10 @@ var baseDifference = require('../internal/baseDifference'), * _.difference([1, 2, 3], [4, 2]); * // => [1, 3] */ -function difference() { - var args = arguments, - index = -1, - length = args.length; - - while (++index < length) { - var value = args[index]; - if (isArray(value) || isArguments(value)) { - break; - } - } - return baseDifference(value, baseFlatten(args, false, true, ++index)); -} +var difference = restParam(function(array, values) { + return (isArray(array) || isArguments(array)) + ? baseDifference(array, baseFlatten(values, false, true)) + : []; +}); module.exports = difference; diff --git a/array/dropRightWhile.js b/array/dropRightWhile.js index 813541007..be158bd5f 100644 --- a/array/dropRightWhile.js +++ b/array/dropRightWhile.js @@ -1,10 +1,10 @@ var baseCallback = require('../internal/baseCallback'), - baseSlice = require('../internal/baseSlice'); + baseWhile = require('../internal/baseWhile'); /** * Creates a slice of `array` excluding elements dropped from the end. * Elements are dropped until `predicate` returns falsey. The predicate is - * bound to `thisArg` and invoked with three arguments; (value, index, array). + * bound to `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -51,13 +51,9 @@ var baseCallback = require('../internal/baseCallback'), * // => ['barney', 'fred', 'pebbles'] */ function dropRightWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - predicate = baseCallback(predicate, thisArg, 3); - while (length-- && predicate(array[length], length, array)) {} - return baseSlice(array, 0, length + 1); + return (array && array.length) + ? baseWhile(array, baseCallback(predicate, thisArg, 3), true, true) + : []; } module.exports = dropRightWhile; diff --git a/array/dropWhile.js b/array/dropWhile.js index 2c8809969..d9eabae9f 100644 --- a/array/dropWhile.js +++ b/array/dropWhile.js @@ -1,10 +1,10 @@ var baseCallback = require('../internal/baseCallback'), - baseSlice = require('../internal/baseSlice'); + baseWhile = require('../internal/baseWhile'); /** * Creates a slice of `array` excluding elements dropped from the beginning. * Elements are dropped until `predicate` returns falsey. The predicate is - * bound to `thisArg` and invoked with three arguments; (value, index, array). + * bound to `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -51,14 +51,9 @@ var baseCallback = require('../internal/baseCallback'), * // => ['barney', 'fred', 'pebbles'] */ function dropWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - var index = -1; - predicate = baseCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) {} - return baseSlice(array, index); + return (array && array.length) + ? baseWhile(array, baseCallback(predicate, thisArg, 3), true) + : []; } module.exports = dropWhile; diff --git a/array/fill.js b/array/fill.js index 44811d309..2c8f6da71 100644 --- a/array/fill.js +++ b/array/fill.js @@ -15,6 +15,19 @@ var baseFill = require('../internal/baseFill'), * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8], '*', 1, 2); + * // => [4, '*', 8] */ function fill(array, value, start, end) { var length = array ? array.length : 0; diff --git a/array/findIndex.js b/array/findIndex.js index 0c2ef3051..2a6b8e14b 100644 --- a/array/findIndex.js +++ b/array/findIndex.js @@ -1,8 +1,8 @@ -var baseCallback = require('../internal/baseCallback'); +var createFindIndex = require('../internal/createFindIndex'); /** * This method is like `_.find` except that it returns the index of the first - * element `predicate` returns truthy for, instead of the element itself. + * element `predicate` returns truthy for instead of the element itself. * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -48,17 +48,6 @@ var baseCallback = require('../internal/baseCallback'); * _.findIndex(users, 'active'); * // => 2 */ -function findIndex(array, predicate, thisArg) { - var index = -1, - length = array ? array.length : 0; - - predicate = baseCallback(predicate, thisArg, 3); - while (++index < length) { - if (predicate(array[index], index, array)) { - return index; - } - } - return -1; -} +var findIndex = createFindIndex(); module.exports = findIndex; diff --git a/array/findLastIndex.js b/array/findLastIndex.js index 7fdcc4ade..d6d8eca6d 100644 --- a/array/findLastIndex.js +++ b/array/findLastIndex.js @@ -1,4 +1,4 @@ -var baseCallback = require('../internal/baseCallback'); +var createFindIndex = require('../internal/createFindIndex'); /** * This method is like `_.findIndex` except that it iterates over elements @@ -48,15 +48,6 @@ var baseCallback = require('../internal/baseCallback'); * _.findLastIndex(users, 'active'); * // => 0 */ -function findLastIndex(array, predicate, thisArg) { - var length = array ? array.length : 0; - predicate = baseCallback(predicate, thisArg, 3); - while (length--) { - if (predicate(array[length], length, array)) { - return length; - } - } - return -1; -} +var findLastIndex = createFindIndex(true); module.exports = findLastIndex; diff --git a/array/flatten.js b/array/flatten.js index 4460c2db6..65bbeefb7 100644 --- a/array/flatten.js +++ b/array/flatten.js @@ -15,18 +15,18 @@ var baseFlatten = require('../internal/baseFlatten'), * @example * * _.flatten([1, [2, 3, [4]]]); - * // => [1, 2, 3, [4]]; + * // => [1, 2, 3, [4]] * * // using `isDeep` * _.flatten([1, [2, 3, [4]]], true); - * // => [1, 2, 3, 4]; + * // => [1, 2, 3, 4] */ function flatten(array, isDeep, guard) { var length = array ? array.length : 0; if (guard && isIterateeCall(array, isDeep, guard)) { isDeep = false; } - return length ? baseFlatten(array, isDeep, false, 0) : []; + return length ? baseFlatten(array, isDeep) : []; } module.exports = flatten; diff --git a/array/flattenDeep.js b/array/flattenDeep.js index ae498bb5b..9f775febe 100644 --- a/array/flattenDeep.js +++ b/array/flattenDeep.js @@ -11,11 +11,11 @@ var baseFlatten = require('../internal/baseFlatten'); * @example * * _.flattenDeep([1, [2, 3, [4]]]); - * // => [1, 2, 3, 4]; + * // => [1, 2, 3, 4] */ function flattenDeep(array) { var length = array ? array.length : 0; - return length ? baseFlatten(array, true, false, 0) : []; + return length ? baseFlatten(array, true) : []; } module.exports = flattenDeep; diff --git a/array/indexOf.js b/array/indexOf.js index b6d2a7d0a..98275997f 100644 --- a/array/indexOf.js +++ b/array/indexOf.js @@ -10,10 +10,9 @@ var nativeMax = Math.max; * it is used as the offset from the end of `array`. If `array` is sorted * providing `true` for `fromIndex` performs a faster binary search. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ diff --git a/array/intersection.js b/array/intersection.js index bc7c8036e..5df24fd2e 100644 --- a/array/intersection.js +++ b/array/intersection.js @@ -8,10 +8,9 @@ var baseIndexOf = require('../internal/baseIndexOf'), * Creates an array of unique values in all provided arrays using `SameValueZero` * for equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ diff --git a/array/pull.js b/array/pull.js index 11e43a3e5..2d4c51752 100644 --- a/array/pull.js +++ b/array/pull.js @@ -11,10 +11,10 @@ var splice = arrayProto.splice; * comparisons. * * **Notes:** - * - Unlike `_.without`, this method mutates `array`. - * - `SameValueZero` comparisons are like strict equality comparisons, e.g. `===`, - * except that `NaN` matches `NaN`. See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * - Unlike `_.without`, this method mutates `array` + * - [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except + * that `NaN` matches `NaN` * * @static * @memberOf _ diff --git a/array/pullAt.js b/array/pullAt.js index 706e73cf9..e48e1c443 100644 --- a/array/pullAt.js +++ b/array/pullAt.js @@ -1,5 +1,14 @@ -var baseFlatten = require('../internal/baseFlatten'), - basePullAt = require('../internal/basePullAt'); +var baseAt = require('../internal/baseAt'), + baseCompareAscending = require('../internal/baseCompareAscending'), + baseFlatten = require('../internal/baseFlatten'), + isIndex = require('../internal/isIndex'), + restParam = require('../function/restParam'); + +/** Used for native method references. */ +var arrayProto = Array.prototype; + +/** Native method references. */ +var splice = arrayProto.splice; /** * Removes elements from `array` corresponding to the given indexes and returns @@ -26,8 +35,22 @@ var baseFlatten = require('../internal/baseFlatten'), * console.log(evens); * // => [10, 20] */ -function pullAt(array) { - return basePullAt(array || [], baseFlatten(arguments, false, false, 1)); -} +var pullAt = restParam(function(array, indexes) { + array || (array = []); + indexes = baseFlatten(indexes); + + var length = indexes.length, + result = baseAt(array, indexes); + + indexes.sort(baseCompareAscending); + while (length--) { + var index = parseFloat(indexes[length]); + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return result; +}); module.exports = pullAt; diff --git a/array/remove.js b/array/remove.js index 52fc526e5..ea2f2cc2d 100644 --- a/array/remove.js +++ b/array/remove.js @@ -9,7 +9,7 @@ var splice = arrayProto.splice; /** * Removes all elements from `array` that `predicate` returns truthy for * and returns an array of the removed elements. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). + * `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. diff --git a/array/sortedIndex.js b/array/sortedIndex.js index fdc5e305e..51d150e3b 100644 --- a/array/sortedIndex.js +++ b/array/sortedIndex.js @@ -1,6 +1,4 @@ -var baseCallback = require('../internal/baseCallback'), - binaryIndex = require('../internal/binaryIndex'), - binaryIndexBy = require('../internal/binaryIndexBy'); +var createSortedIndex = require('../internal/createSortedIndex'); /** * Uses a binary search to determine the lowest index at which `value` should @@ -9,14 +7,14 @@ var baseCallback = require('../internal/baseCallback'), * to compute their sort ranking. The iteratee is bound to `thisArg` and * invoked with one argument; (value). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -50,10 +48,6 @@ var baseCallback = require('../internal/baseCallback'), * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ -function sortedIndex(array, value, iteratee, thisArg) { - return iteratee == null - ? binaryIndex(array, value) - : binaryIndexBy(array, value, baseCallback(iteratee, thisArg, 1)); -} +var sortedIndex = createSortedIndex(); module.exports = sortedIndex; diff --git a/array/sortedLastIndex.js b/array/sortedLastIndex.js index 6936d4e6c..81a4a8689 100644 --- a/array/sortedLastIndex.js +++ b/array/sortedLastIndex.js @@ -1,6 +1,4 @@ -var baseCallback = require('../internal/baseCallback'), - binaryIndex = require('../internal/binaryIndex'), - binaryIndexBy = require('../internal/binaryIndexBy'); +var createSortedIndex = require('../internal/createSortedIndex'); /** * This method is like `_.sortedIndex` except that it returns the highest @@ -22,10 +20,6 @@ var baseCallback = require('../internal/baseCallback'), * _.sortedLastIndex([4, 4, 5, 5], 5); * // => 4 */ -function sortedLastIndex(array, value, iteratee, thisArg) { - return iteratee == null - ? binaryIndex(array, value, true) - : binaryIndexBy(array, value, baseCallback(iteratee, thisArg, 1), true); -} +var sortedLastIndex = createSortedIndex(true); module.exports = sortedLastIndex; diff --git a/array/takeRightWhile.js b/array/takeRightWhile.js index 57bb0ef06..5464d13b7 100644 --- a/array/takeRightWhile.js +++ b/array/takeRightWhile.js @@ -1,10 +1,10 @@ var baseCallback = require('../internal/baseCallback'), - baseSlice = require('../internal/baseSlice'); + baseWhile = require('../internal/baseWhile'); /** * Creates a slice of `array` with elements taken from the end. Elements are * taken until `predicate` returns falsey. The predicate is bound to `thisArg` - * and invoked with three arguments; (value, index, array). + * and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -51,13 +51,9 @@ var baseCallback = require('../internal/baseCallback'), * // => [] */ function takeRightWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - predicate = baseCallback(predicate, thisArg, 3); - while (length-- && predicate(array[length], length, array)) {} - return baseSlice(array, length + 1); + return (array && array.length) + ? baseWhile(array, baseCallback(predicate, thisArg, 3), false, true) + : []; } module.exports = takeRightWhile; diff --git a/array/takeWhile.js b/array/takeWhile.js index 890e34a60..f7e28a1d4 100644 --- a/array/takeWhile.js +++ b/array/takeWhile.js @@ -1,10 +1,10 @@ var baseCallback = require('../internal/baseCallback'), - baseSlice = require('../internal/baseSlice'); + baseWhile = require('../internal/baseWhile'); /** * Creates a slice of `array` with elements taken from the beginning. Elements * are taken until `predicate` returns falsey. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). + * `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -51,14 +51,9 @@ var baseCallback = require('../internal/baseCallback'), * // => [] */ function takeWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - var index = -1; - predicate = baseCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) {} - return baseSlice(array, 0, index); + return (array && array.length) + ? baseWhile(array, baseCallback(predicate, thisArg, 3)) + : []; } module.exports = takeWhile; diff --git a/array/union.js b/array/union.js index bb78dac34..312b39525 100644 --- a/array/union.js +++ b/array/union.js @@ -1,14 +1,14 @@ var baseFlatten = require('../internal/baseFlatten'), - baseUniq = require('../internal/baseUniq'); + baseUniq = require('../internal/baseUniq'), + restParam = require('../function/restParam'); /** * Creates an array of unique values, in order, of the provided arrays using * `SameValueZero` for equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -20,8 +20,8 @@ var baseFlatten = require('../internal/baseFlatten'), * _.union([1, 2], [4, 2], [2, 1]); * // => [1, 2, 4] */ -function union() { - return baseUniq(baseFlatten(arguments, false, true, 0)); -} +var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); +}); module.exports = union; diff --git a/array/uniq.js b/array/uniq.js index 6b3032809..e34213a22 100644 --- a/array/uniq.js +++ b/array/uniq.js @@ -9,23 +9,22 @@ var baseCallback = require('../internal/baseCallback'), * search algorithm for sorted arrays. If an iteratee function is provided it * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked - * with three arguments; (value, index, array). + * with three arguments: (value, index, array). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ diff --git a/array/without.js b/array/without.js index e74c40396..7927ba144 100644 --- a/array/without.js +++ b/array/without.js @@ -1,14 +1,15 @@ var baseDifference = require('../internal/baseDifference'), - baseSlice = require('../internal/baseSlice'); + isArguments = require('../lang/isArguments'), + isArray = require('../lang/isArray'), + restParam = require('../function/restParam'); /** * Creates an array excluding all provided values using `SameValueZero` for * equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -21,8 +22,10 @@ var baseDifference = require('../internal/baseDifference'), * _.without([1, 2, 1, 3], 1, 2); * // => [3] */ -function without(array) { - return baseDifference(array, baseSlice(arguments, 1)); -} +var without = restParam(function(array, values) { + return (isArray(array) || isArguments(array)) + ? baseDifference(array, values) + : []; +}); module.exports = without; diff --git a/array/xor.js b/array/xor.js index fcdec8eb5..77638775d 100644 --- a/array/xor.js +++ b/array/xor.js @@ -4,9 +4,8 @@ var baseDifference = require('../internal/baseDifference'), isArray = require('../lang/isArray'); /** - * Creates an array that is the symmetric difference of the provided arrays. - * See [Wikipedia](https://en.wikipedia.org/wiki/Symmetric_difference) for - * more details. + * Creates an array that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the provided arrays. * * @static * @memberOf _ diff --git a/array/zip.js b/array/zip.js index 039bac0a9..53a6f6991 100644 --- a/array/zip.js +++ b/array/zip.js @@ -1,4 +1,5 @@ -var unzip = require('./unzip'); +var restParam = require('../function/restParam'), + unzip = require('./unzip'); /** * Creates an array of grouped elements, the first of which contains the first @@ -15,14 +16,6 @@ var unzip = require('./unzip'); * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] */ -function zip() { - var length = arguments.length, - array = Array(length); - - while (length--) { - array[length] = arguments[length]; - } - return unzip(array); -} +var zip = restParam(unzip); module.exports = zip; diff --git a/array/zipObject.js b/array/zipObject.js index bc3f9522e..dec7a211b 100644 --- a/array/zipObject.js +++ b/array/zipObject.js @@ -1,9 +1,10 @@ var isArray = require('../lang/isArray'); /** - * Creates an object composed from arrays of property names and values. Provide - * either a single two dimensional array, e.g. `[[key1, value1], [key2, value2]]` - * or two arrays, one of property names and one of corresponding values. + * The inverse of `_.pairs`; this method returns an object composed from arrays + * of property names and values. Provide either a single two dimensional array, + * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names + * and one of corresponding values. * * @static * @memberOf _ @@ -14,6 +15,9 @@ var isArray = require('../lang/isArray'); * @returns {Object} Returns the new object. * @example * + * _.zipObject([['fred', 30], ['barney', 40]]); + * // => { 'fred': 30, 'barney': 40 } + * * _.zipObject(['fred', 'barney'], [30, 40]); * // => { 'fred': 30, 'barney': 40 } */ diff --git a/chain/thru.js b/chain/thru.js index 8ccc99696..a71578037 100644 --- a/chain/thru.js +++ b/chain/thru.js @@ -10,13 +10,14 @@ * @returns {*} Returns the result of `interceptor`. * @example * - * _([1, 2, 3]) - * .last() + * _(' abc ') + * .chain() + * .trim() * .thru(function(value) { * return [value]; * }) * .value(); - * // => [3] + * // => ['abc'] */ function thru(value, interceptor, thisArg) { return interceptor.call(thisArg, value); diff --git a/collection/at.js b/collection/at.js index 48a714f6b..f99141a9f 100644 --- a/collection/at.js +++ b/collection/at.js @@ -1,6 +1,7 @@ var baseAt = require('../internal/baseAt'), baseFlatten = require('../internal/baseFlatten'), isLength = require('../internal/isLength'), + restParam = require('../function/restParam'), toIterable = require('../internal/toIterable'); /** @@ -20,15 +21,15 @@ var baseAt = require('../internal/baseAt'), * _.at(['a', 'b', 'c'], [0, 2]); * // => ['a', 'c'] * - * _.at(['fred', 'barney', 'pebbles'], 0, 2); - * // => ['fred', 'pebbles'] + * _.at(['barney', 'fred', 'pebbles'], 0, 2); + * // => ['barney', 'pebbles'] */ -function at(collection) { +var at = restParam(function(collection, props) { var length = collection ? collection.length : 0; if (isLength(length)) { collection = toIterable(collection); } - return baseAt(collection, baseFlatten(arguments, false, false, 1)); -} + return baseAt(collection, baseFlatten(props)); +}); module.exports = at; diff --git a/collection/countBy.js b/collection/countBy.js index 7702d7bf1..e97dbb749 100644 --- a/collection/countBy.js +++ b/collection/countBy.js @@ -10,17 +10,17 @@ var hasOwnProperty = objectProto.hasOwnProperty; * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the number of times the key was returned by `iteratee`. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * diff --git a/collection/every.js b/collection/every.js index 276afb3ed..82a598cdf 100644 --- a/collection/every.js +++ b/collection/every.js @@ -1,11 +1,12 @@ var arrayEvery = require('../internal/arrayEvery'), baseCallback = require('../internal/baseCallback'), baseEvery = require('../internal/baseEvery'), - isArray = require('../lang/isArray'); + isArray = require('../lang/isArray'), + isIterateeCall = require('../internal/isIterateeCall'); /** * Checks if `predicate` returns truthy for **all** elements of `collection`. - * The predicate is bound to `thisArg` and invoked with three arguments; + * The predicate is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` @@ -53,6 +54,9 @@ var arrayEvery = require('../internal/arrayEvery'), */ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = null; + } if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = baseCallback(predicate, thisArg, 3); } diff --git a/collection/filter.js b/collection/filter.js index 673ae22b8..7620aa761 100644 --- a/collection/filter.js +++ b/collection/filter.js @@ -6,7 +6,7 @@ var arrayFilter = require('../internal/arrayFilter'), /** * Iterates over elements of `collection`, returning an array of all elements * `predicate` returns truthy for. The predicate is bound to `thisArg` and - * invoked with three arguments; (value, index|key, collection). + * invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. diff --git a/collection/find.js b/collection/find.js index 8e687d833..7358cfe86 100644 --- a/collection/find.js +++ b/collection/find.js @@ -1,13 +1,10 @@ -var baseCallback = require('../internal/baseCallback'), - baseEach = require('../internal/baseEach'), - baseFind = require('../internal/baseFind'), - findIndex = require('../array/findIndex'), - isArray = require('../lang/isArray'); +var baseEach = require('../internal/baseEach'), + createFind = require('../internal/createFind'); /** * Iterates over elements of `collection`, returning the first element * `predicate` returns truthy for. The predicate is bound to `thisArg` and - * invoked with three arguments; (value, index|key, collection). + * invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -54,13 +51,6 @@ var baseCallback = require('../internal/baseCallback'), * _.result(_.find(users, 'active'), 'user'); * // => 'barney' */ -function find(collection, predicate, thisArg) { - if (isArray(collection)) { - var index = findIndex(collection, predicate, thisArg); - return index > -1 ? collection[index] : undefined; - } - predicate = baseCallback(predicate, thisArg, 3); - return baseFind(collection, predicate, baseEach); -} +var find = createFind(baseEach); module.exports = find; diff --git a/collection/findLast.js b/collection/findLast.js index f66f6cc85..75dbadca2 100644 --- a/collection/findLast.js +++ b/collection/findLast.js @@ -1,6 +1,5 @@ -var baseCallback = require('../internal/baseCallback'), - baseEachRight = require('../internal/baseEachRight'), - baseFind = require('../internal/baseFind'); +var baseEachRight = require('../internal/baseEachRight'), + createFind = require('../internal/createFind'); /** * This method is like `_.find` except that it iterates over elements of @@ -21,9 +20,6 @@ var baseCallback = require('../internal/baseCallback'), * }); * // => 3 */ -function findLast(collection, predicate, thisArg) { - predicate = baseCallback(predicate, thisArg, 3); - return baseFind(collection, predicate, baseEachRight); -} +var findLast = createFind(baseEachRight, true); module.exports = findLast; diff --git a/collection/forEach.js b/collection/forEach.js index 38cf79672..c899d91cf 100644 --- a/collection/forEach.js +++ b/collection/forEach.js @@ -1,11 +1,10 @@ var arrayEach = require('../internal/arrayEach'), baseEach = require('../internal/baseEach'), - bindCallback = require('../internal/bindCallback'), - isArray = require('../lang/isArray'); + createForEach = require('../internal/createForEach'); /** * Iterates over elements of `collection` invoking `iteratee` for each element. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -33,10 +32,6 @@ var arrayEach = require('../internal/arrayEach'), * }); * // => logs each value-key pair and returns the object (iteration order is not guaranteed) */ -function forEach(collection, iteratee, thisArg) { - return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, iteratee) - : baseEach(collection, bindCallback(iteratee, thisArg, 3)); -} +var forEach = createForEach(arrayEach, baseEach); module.exports = forEach; diff --git a/collection/forEachRight.js b/collection/forEachRight.js index 56bb8ffe3..349971100 100644 --- a/collection/forEachRight.js +++ b/collection/forEachRight.js @@ -1,7 +1,6 @@ var arrayEachRight = require('../internal/arrayEachRight'), baseEachRight = require('../internal/baseEachRight'), - bindCallback = require('../internal/bindCallback'), - isArray = require('../lang/isArray'); + createForEach = require('../internal/createForEach'); /** * This method is like `_.forEach` except that it iterates over elements of @@ -19,13 +18,9 @@ var arrayEachRight = require('../internal/arrayEachRight'), * * _([1, 2]).forEachRight(function(n) { * console.log(n); - * }).join(','); + * }).value(); * // => logs each value from right to left and returns the array */ -function forEachRight(collection, iteratee, thisArg) { - return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEachRight(collection, iteratee) - : baseEachRight(collection, bindCallback(iteratee, thisArg, 3)); -} +var forEachRight = createForEach(arrayEachRight, baseEachRight); module.exports = forEachRight; diff --git a/collection/groupBy.js b/collection/groupBy.js index f2578b3f9..a925c894a 100644 --- a/collection/groupBy.js +++ b/collection/groupBy.js @@ -10,17 +10,17 @@ var hasOwnProperty = objectProto.hasOwnProperty; * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is an array of the elements responsible for generating the key. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * diff --git a/collection/includes.js b/collection/includes.js index a383fabed..76da61d46 100644 --- a/collection/includes.js +++ b/collection/includes.js @@ -1,5 +1,6 @@ var baseIndexOf = require('../internal/baseIndexOf'), isArray = require('../lang/isArray'), + isIterateeCall = require('../internal/isIterateeCall'), isLength = require('../internal/isLength'), isString = require('../lang/isString'), values = require('../object/values'); @@ -12,10 +13,9 @@ var nativeMax = Math.max; * comparisons. If `fromIndex` is negative, it is used as the offset from * the end of `collection`. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -24,6 +24,7 @@ var nativeMax = Math.max; * @param {Array|Object|string} collection The collection to search. * @param {*} target The value to search for. * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {boolean} Returns `true` if a matching element is found, else `false`. * @example * @@ -39,7 +40,7 @@ var nativeMax = Math.max; * _.includes('pebbles', 'eb'); * // => true */ -function includes(collection, target, fromIndex) { +function includes(collection, target, fromIndex, guard) { var length = collection ? collection.length : 0; if (!isLength(length)) { collection = values(collection); @@ -48,10 +49,10 @@ function includes(collection, target, fromIndex) { if (!length) { return false; } - if (typeof fromIndex == 'number') { - fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); - } else { + if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) diff --git a/collection/indexBy.js b/collection/indexBy.js index 0cc42d5fe..34a941e72 100644 --- a/collection/indexBy.js +++ b/collection/indexBy.js @@ -4,17 +4,17 @@ var createAggregator = require('../internal/createAggregator'); * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The - * iteratee function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * diff --git a/collection/invoke.js b/collection/invoke.js index c305a0473..a45463d4d 100644 --- a/collection/invoke.js +++ b/collection/invoke.js @@ -1,5 +1,6 @@ -var baseInvoke = require('../internal/baseInvoke'), - baseSlice = require('../internal/baseSlice'); +var baseEach = require('../internal/baseEach'), + isLength = require('../internal/isLength'), + restParam = require('../function/restParam'); /** * Invokes the method named by `methodName` on each element in `collection`, @@ -23,8 +24,17 @@ var baseInvoke = require('../internal/baseInvoke'), * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ -function invoke(collection, methodName) { - return baseInvoke(collection, methodName, baseSlice(arguments, 2)); -} +var invoke = restParam(function(collection, methodName, args) { + var index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = isLength(length) ? Array(length) : []; + + baseEach(collection, function(value) { + var func = isFunc ? methodName : (value != null && value[methodName]); + result[++index] = func ? func.apply(value, args) : undefined; + }); + return result; +}); module.exports = invoke; diff --git a/collection/map.js b/collection/map.js index f918be61c..f216fa222 100644 --- a/collection/map.js +++ b/collection/map.js @@ -6,16 +6,16 @@ var arrayMap = require('../internal/arrayMap'), /** * Creates an array of values by running each element in `collection` through * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three - * arguments; (value, index|key, collection). + * arguments: (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -24,9 +24,9 @@ var arrayMap = require('../internal/arrayMap'), * * The guarded methods are: * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, `drop`, - * `dropRight`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`, `slice`, - * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`, `trimRight`, - * `trunc`, `random`, `range`, `sample`, `uniq`, and `words` + * `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`, + * `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`, + * `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, `uniq`, and `words` * * @static * @memberOf _ diff --git a/collection/partition.js b/collection/partition.js index 4a5bdbe00..ee35f27d9 100644 --- a/collection/partition.js +++ b/collection/partition.js @@ -4,7 +4,7 @@ var createAggregator = require('../internal/createAggregator'); * Creates an array of elements split into two groups, the first of which * contains elements `predicate` returns truthy for, while the second of which * contains elements `predicate` returns falsey for. The predicate is bound - * to `thisArg` and invoked with three arguments; (value, index|key, collection). + * to `thisArg` and invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. diff --git a/collection/reduce.js b/collection/reduce.js index f02fd9c8f..e89781fb9 100644 --- a/collection/reduce.js +++ b/collection/reduce.js @@ -1,22 +1,20 @@ var arrayReduce = require('../internal/arrayReduce'), - baseCallback = require('../internal/baseCallback'), baseEach = require('../internal/baseEach'), - baseReduce = require('../internal/baseReduce'), - isArray = require('../lang/isArray'); + createReduce = require('../internal/createReduce'); /** * Reduces `collection` to a value which is the accumulated result of running * each element in `collection` through `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of `collection` is used as the initial - * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; + * value. The `iteratee` is bound to `thisArg` and invoked with four arguments: * (accumulator, value, index|key, collection). * * Many lodash methods are guarded to work as interatees for methods like * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: - * `assign`, `defaults`, `merge`, and `sortAllBy` + * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` * * @static * @memberOf _ @@ -40,9 +38,6 @@ var arrayReduce = require('../internal/arrayReduce'), * }, {}); * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed) */ -function reduce(collection, iteratee, accumulator, thisArg) { - var func = isArray(collection) ? arrayReduce : baseReduce; - return func(collection, baseCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); -} +var reduce = createReduce(arrayReduce, baseEach); module.exports = reduce; diff --git a/collection/reduceRight.js b/collection/reduceRight.js index d51763245..b40e3338e 100644 --- a/collection/reduceRight.js +++ b/collection/reduceRight.js @@ -1,8 +1,6 @@ var arrayReduceRight = require('../internal/arrayReduceRight'), - baseCallback = require('../internal/baseCallback'), baseEachRight = require('../internal/baseEachRight'), - baseReduce = require('../internal/baseReduce'), - isArray = require('../lang/isArray'); + createReduce = require('../internal/createReduce'); /** * This method is like `_.reduce` except that it iterates over elements of @@ -26,9 +24,6 @@ var arrayReduceRight = require('../internal/arrayReduceRight'), * }, []); * // => [4, 5, 2, 3, 0, 1] */ -function reduceRight(collection, iteratee, accumulator, thisArg) { - var func = isArray(collection) ? arrayReduceRight : baseReduce; - return func(collection, baseCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); -} +var reduceRight = createReduce(arrayReduceRight, baseEachRight); module.exports = reduceRight; diff --git a/collection/shuffle.js b/collection/shuffle.js index 7548c1a81..2281d4f65 100644 --- a/collection/shuffle.js +++ b/collection/shuffle.js @@ -2,9 +2,8 @@ var baseRandom = require('../internal/baseRandom'), toIterable = require('../internal/toIterable'); /** - * Creates an array of shuffled values, using a version of the Fisher-Yates - * shuffle. See [Wikipedia](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle) - * for more details. + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). * * @static * @memberOf _ diff --git a/collection/some.js b/collection/some.js index e256773ae..b1cba1fdb 100644 --- a/collection/some.js +++ b/collection/some.js @@ -1,13 +1,14 @@ var arraySome = require('../internal/arraySome'), baseCallback = require('../internal/baseCallback'), baseSome = require('../internal/baseSome'), - isArray = require('../lang/isArray'); + isArray = require('../lang/isArray'), + isIterateeCall = require('../internal/isIterateeCall'); /** * Checks if `predicate` returns truthy for **any** element of `collection`. * The function returns as soon as it finds a passing value and does not iterate * over the entire collection. The predicate is bound to `thisArg` and invoked - * with three arguments; (value, index|key, collection). + * with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -54,6 +55,9 @@ var arraySome = require('../internal/arraySome'), */ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = null; + } if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = baseCallback(predicate, thisArg, 3); } diff --git a/collection/sortBy.js b/collection/sortBy.js index b0f68badf..c64231da5 100644 --- a/collection/sortBy.js +++ b/collection/sortBy.js @@ -9,17 +9,17 @@ var baseCallback = require('../internal/baseCallback'), * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * diff --git a/collection/sortByAll.js b/collection/sortByAll.js index 94339890b..cd72c45b8 100644 --- a/collection/sortByAll.js +++ b/collection/sortByAll.js @@ -25,17 +25,24 @@ var baseFlatten = require('../internal/baseFlatten'), * _.map(_.sortByAll(users, ['user', 'age']), _.values); * // => [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ -function sortByAll(collection) { +function sortByAll() { + var args = arguments, + collection = args[0], + guard = args[3], + index = 0, + length = args.length - 1; + if (collection == null) { return []; } - var args = arguments, - guard = args[3]; - - if (guard && isIterateeCall(args[1], args[2], guard)) { - args = [collection, args[1]]; + var props = Array(length); + while (index < length) { + props[index] = args[++index]; } - return baseSortByOrder(collection, baseFlatten(args, false, false, 1), []); + if (guard && isIterateeCall(args[1], args[2], guard)) { + props = args[1]; + } + return baseSortByOrder(collection, baseFlatten(props), []); } module.exports = sortByAll; diff --git a/function.js b/function.js index 33ccefc3a..2cacde1ee 100644 --- a/function.js +++ b/function.js @@ -20,6 +20,7 @@ module.exports = { 'partial': require('./function/partial'), 'partialRight': require('./function/partialRight'), 'rearg': require('./function/rearg'), + 'restParam': require('./function/restParam'), 'spread': require('./function/spread'), 'throttle': require('./function/throttle'), 'wrap': require('./function/wrap') diff --git a/function/ary.js b/function/ary.js index 9604c1bfe..1bcb6a720 100644 --- a/function/ary.js +++ b/function/ary.js @@ -2,7 +2,7 @@ var createWrapper = require('../internal/createWrapper'), isIterateeCall = require('../internal/isIterateeCall'); /** Used to compose bitmasks for wrapper metadata. */ -var ARY_FLAG = 256; +var ARY_FLAG = 128; /* Native method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; diff --git a/function/bind.js b/function/bind.js index 155df051b..22e20e92a 100644 --- a/function/bind.js +++ b/function/bind.js @@ -1,6 +1,6 @@ -var baseSlice = require('../internal/baseSlice'), - createWrapper = require('../internal/createWrapper'), - replaceHolders = require('../internal/replaceHolders'); +var createWrapper = require('../internal/createWrapper'), + replaceHolders = require('../internal/replaceHolders'), + restParam = require('./restParam'); /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -22,7 +22,7 @@ var BIND_FLAG = 1, * @category Function * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * @@ -41,16 +41,14 @@ var BIND_FLAG = 1, * bound('hi'); * // => 'hi fred!' */ -function bind(func, thisArg) { +var bind = restParam(function(func, thisArg, partials) { var bitmask = BIND_FLAG; - if (arguments.length > 2) { - var partials = baseSlice(arguments, 2), - holders = replaceHolders(partials, bind.placeholder); - + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(func, bitmask, thisArg, partials, holders); -} +}); // Assign default placeholders. bind.placeholder = {}; diff --git a/function/bindAll.js b/function/bindAll.js index 82db5dc04..e2f47f9f6 100644 --- a/function/bindAll.js +++ b/function/bindAll.js @@ -1,6 +1,10 @@ -var baseBindAll = require('../internal/baseBindAll'), - baseFlatten = require('../internal/baseFlatten'), - functions = require('../object/functions'); +var baseFlatten = require('../internal/baseFlatten'), + createWrapper = require('../internal/createWrapper'), + functions = require('../object/functions'), + restParam = require('./restParam'); + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1; /** * Binds methods of an object to the object itself, overwriting the existing @@ -30,12 +34,17 @@ var baseBindAll = require('../internal/baseBindAll'), * jQuery('#docs').on('click', view.onClick); * // => logs 'clicked docs' when the element is clicked */ -function bindAll(object) { - return baseBindAll(object, - arguments.length > 1 - ? baseFlatten(arguments, false, false, 1) - : functions(object) - ); -} +var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + + var index = -1, + length = methodNames.length; + + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; +}); module.exports = bindAll; diff --git a/function/bindKey.js b/function/bindKey.js index 8098d16a6..0307d24f2 100644 --- a/function/bindKey.js +++ b/function/bindKey.js @@ -1,6 +1,6 @@ -var baseSlice = require('../internal/baseSlice'), - createWrapper = require('../internal/createWrapper'), - replaceHolders = require('../internal/replaceHolders'); +var createWrapper = require('../internal/createWrapper'), + replaceHolders = require('../internal/replaceHolders'), + restParam = require('./restParam'); /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -24,7 +24,7 @@ var BIND_FLAG = 1, * @category Function * @param {Object} object The object the method belongs to. * @param {string} key The key of the method. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * @@ -51,16 +51,14 @@ var BIND_FLAG = 1, * bound('hi'); * // => 'hiya fred!' */ -function bindKey(object, key) { +var bindKey = restParam(function(object, key, partials) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; - if (arguments.length > 2) { - var partials = baseSlice(arguments, 2), - holders = replaceHolders(partials, bindKey.placeholder); - + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(key, bitmask, object, partials, holders); -} +}); // Assign default placeholders. bindKey.placeholder = {}; diff --git a/function/curry.js b/function/curry.js index 5f7afafdd..37cb17f6b 100644 --- a/function/curry.js +++ b/function/curry.js @@ -1,5 +1,4 @@ -var createWrapper = require('../internal/createWrapper'), - isIterateeCall = require('../internal/isIterateeCall'); +var createCurry = require('../internal/createCurry'); /** Used to compose bitmasks for wrapper metadata. */ var CURRY_FLAG = 8; @@ -44,14 +43,7 @@ var CURRY_FLAG = 8; * curried(1)(_, 3)(2); * // => [1, 2, 3] */ -function curry(func, arity, guard) { - if (guard && isIterateeCall(func, arity, guard)) { - arity = null; - } - var result = createWrapper(func, CURRY_FLAG, null, null, null, null, null, arity); - result.placeholder = curry.placeholder; - return result; -} +var curry = createCurry(CURRY_FLAG); // Assign default placeholders. curry.placeholder = {}; diff --git a/function/curryRight.js b/function/curryRight.js index c36ab218e..f2586b046 100644 --- a/function/curryRight.js +++ b/function/curryRight.js @@ -1,5 +1,4 @@ -var createWrapper = require('../internal/createWrapper'), - isIterateeCall = require('../internal/isIterateeCall'); +var createCurry = require('../internal/createCurry'); /** Used to compose bitmasks for wrapper metadata. */ var CURRY_RIGHT_FLAG = 16; @@ -41,14 +40,7 @@ var CURRY_RIGHT_FLAG = 16; * curried(3)(1, _)(2); * // => [1, 2, 3] */ -function curryRight(func, arity, guard) { - if (guard && isIterateeCall(func, arity, guard)) { - arity = null; - } - var result = createWrapper(func, CURRY_RIGHT_FLAG, null, null, null, null, null, arity); - result.placeholder = curryRight.placeholder; - return result; -} +var curryRight = createCurry(CURRY_RIGHT_FLAG); // Assign default placeholders. curryRight.placeholder = {}; diff --git a/function/defer.js b/function/defer.js index ed31c24e1..369790ce6 100644 --- a/function/defer.js +++ b/function/defer.js @@ -1,4 +1,5 @@ -var baseDelay = require('../internal/baseDelay'); +var baseDelay = require('../internal/baseDelay'), + restParam = require('./restParam'); /** * Defers invoking the `func` until the current call stack has cleared. Any @@ -17,8 +18,8 @@ var baseDelay = require('../internal/baseDelay'); * }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ -function defer(func) { - return baseDelay(func, 1, arguments, 1); -} +var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); +}); module.exports = defer; diff --git a/function/delay.js b/function/delay.js index 889e57778..955b059e7 100644 --- a/function/delay.js +++ b/function/delay.js @@ -1,4 +1,5 @@ -var baseDelay = require('../internal/baseDelay'); +var baseDelay = require('../internal/baseDelay'), + restParam = require('./restParam'); /** * Invokes `func` after `wait` milliseconds. Any additional arguments are @@ -18,8 +19,8 @@ var baseDelay = require('../internal/baseDelay'); * }, 1000, 'later'); * // => logs 'later' after one second */ -function delay(func, wait) { - return baseDelay(func, wait, arguments, 2); -} +var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); +}); module.exports = delay; diff --git a/function/flow.js b/function/flow.js index da946f201..a435a3d87 100644 --- a/function/flow.js +++ b/function/flow.js @@ -1,4 +1,4 @@ -var createComposer = require('../internal/createComposer'); +var createFlow = require('../internal/createFlow'); /** * Creates a function that returns the result of invoking the provided @@ -20,6 +20,6 @@ var createComposer = require('../internal/createComposer'); * addSquare(1, 2); * // => 9 */ -var flow = createComposer(); +var flow = createFlow(); module.exports = flow; diff --git a/function/flowRight.js b/function/flowRight.js index f7981b32c..23b9d76b5 100644 --- a/function/flowRight.js +++ b/function/flowRight.js @@ -1,4 +1,4 @@ -var createComposer = require('../internal/createComposer'); +var createFlow = require('../internal/createFlow'); /** * This method is like `_.flow` except that it creates a function that @@ -20,6 +20,6 @@ var createComposer = require('../internal/createComposer'); * addSquare(1, 2); * // => 9 */ -var flowRight = createComposer(true); +var flowRight = createFlow(true); module.exports = flowRight; diff --git a/function/memoize.js b/function/memoize.js index f80f4a9fa..c9de9897c 100644 --- a/function/memoize.js +++ b/function/memoize.js @@ -13,10 +13,8 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the ES `Map` method interface - * of `get`, `has`, and `set`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) - * for more details. + * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * method interface of `get`, `has`, and `set`. * * @static * @memberOf _ diff --git a/function/once.js b/function/once.js index 90c0ae9ab..96ef5d170 100644 --- a/function/once.js +++ b/function/once.js @@ -3,7 +3,7 @@ var before = require('./before'); /** * Creates a function that is restricted to invoking `func` once. Repeat calls * to the function return the value of the first call. The `func` is invoked - * with the `this` binding of the created function. + * with the `this` binding and arguments of the created function. * * @static * @memberOf _ diff --git a/function/partial.js b/function/partial.js index 70a1f9f92..2b72559a8 100644 --- a/function/partial.js +++ b/function/partial.js @@ -1,6 +1,4 @@ -var baseSlice = require('../internal/baseSlice'), - createWrapper = require('../internal/createWrapper'), - replaceHolders = require('../internal/replaceHolders'); +var createPartial = require('../internal/createPartial'); /** Used to compose bitmasks for wrapper metadata. */ var PARTIAL_FLAG = 32; @@ -20,7 +18,7 @@ var PARTIAL_FLAG = 32; * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * @@ -37,12 +35,7 @@ var PARTIAL_FLAG = 32; * greetFred('hi'); * // => 'hi fred' */ -function partial(func) { - var partials = baseSlice(arguments, 1), - holders = replaceHolders(partials, partial.placeholder); - - return createWrapper(func, PARTIAL_FLAG, null, partials, holders); -} +var partial = createPartial(PARTIAL_FLAG); // Assign default placeholders. partial.placeholder = {}; diff --git a/function/partialRight.js b/function/partialRight.js index 1587ad02c..5f45005fc 100644 --- a/function/partialRight.js +++ b/function/partialRight.js @@ -1,6 +1,4 @@ -var baseSlice = require('../internal/baseSlice'), - createWrapper = require('../internal/createWrapper'), - replaceHolders = require('../internal/replaceHolders'); +var createPartial = require('../internal/createPartial'); /** Used to compose bitmasks for wrapper metadata. */ var PARTIAL_RIGHT_FLAG = 64; @@ -19,7 +17,7 @@ var PARTIAL_RIGHT_FLAG = 64; * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * @@ -36,12 +34,7 @@ var PARTIAL_RIGHT_FLAG = 64; * sayHelloTo('fred'); * // => 'hello fred' */ -function partialRight(func) { - var partials = baseSlice(arguments, 1), - holders = replaceHolders(partials, partialRight.placeholder); - - return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders); -} +var partialRight = createPartial(PARTIAL_RIGHT_FLAG); // Assign default placeholders. partialRight.placeholder = {}; diff --git a/function/rearg.js b/function/rearg.js index a1bcd5296..0a4bf8fa6 100644 --- a/function/rearg.js +++ b/function/rearg.js @@ -1,8 +1,9 @@ var baseFlatten = require('../internal/baseFlatten'), - createWrapper = require('../internal/createWrapper'); + createWrapper = require('../internal/createWrapper'), + restParam = require('./restParam'); /** Used to compose bitmasks for wrapper metadata. */ -var REARG_FLAG = 128; +var REARG_FLAG = 256; /** * Creates a function that invokes `func` with arguments arranged according @@ -32,9 +33,8 @@ var REARG_FLAG = 128; * }, [1, 2, 3]); * // => [3, 6, 9] */ -function rearg(func) { - var indexes = baseFlatten(arguments, false, false, 1); - return createWrapper(func, REARG_FLAG, null, null, null, indexes); -} +var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes)); +}); module.exports = rearg; diff --git a/function/restParam.js b/function/restParam.js new file mode 100644 index 000000000..bc9ec237b --- /dev/null +++ b/function/restParam.js @@ -0,0 +1,58 @@ +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as an array. + * + * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters). + * + * @static + * @memberOf _ + * @category Function + * @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. + * @example + * + * var say = _.restParam(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ +function restParam(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(typeof start == 'undefined' ? (func.length - 1) : (+start || 0), 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + rest = Array(length); + + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: return func.call(this, rest); + case 1: return func.call(this, args[0], rest); + case 2: return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; +} + +module.exports = restParam; diff --git a/function/spread.js b/function/spread.js index a14d72a64..aad4b7147 100644 --- a/function/spread.js +++ b/function/spread.js @@ -2,23 +2,24 @@ var FUNC_ERROR_TEXT = 'Expected a function'; /** - * Creates a function that invokes `func` with the `this` binding of the - * created function and the array of arguments provided to the created - * function much like [Function#apply](http://es5.github.io/#x15.3.4.3). + * Creates a function that invokes `func` with the `this` binding of the created + * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3). + * + * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). * * @static * @memberOf _ * @category Function * @param {Function} func The function to spread arguments over. - * @returns {*} Returns the new function. + * @returns {Function} Returns the new function. * @example * - * var spread = _.spread(function(who, what) { + * var say = _.spread(function(who, what) { * return who + ' says ' + what; * }); * - * spread(['Fred', 'hello']); - * // => 'Fred says hello' + * say(['fred', 'hello']); + * // => 'fred says hello' * * // with a Promise * var numbers = Promise.all([ diff --git a/index.js b/index.js index 52b19d79b..6e8bd2f0e 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ /** * @license - * lodash 3.5.0 (Custom Build) + * lodash 3.6.0 (Custom Build) * Build: `lodash modern -d -o ./index.js` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.8.2 @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '3.5.0'; + var VERSION = '3.6.0'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -23,8 +23,8 @@ CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, - REARG_FLAG = 128, - ARY_FLAG = 256; + ARY_FLAG = 128, + REARG_FLAG = 256; /** Used as default options for `_.trunc`. */ var DEFAULT_TRUNC_LENGTH = 30, @@ -88,18 +88,18 @@ reInterpolate = /<%=([\s\S]+?)%>/g; /** - * Used to match ES template delimiters. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) - * for more details. + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + */ + var reComboMarks = /[\u0300-\u036f\ufe20-\ufe23]/g; + + /** + * Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; - /** Used to detect named functions. */ - var reFuncName = /^\s*function[ \n\r\t]+\w/; - /** Used to detect hexadecimal string values. */ var reHexPrefix = /^0[xX]/; @@ -113,16 +113,13 @@ var reNoMatch = /($^)/; /** - * Used to match `RegExp` special characters. - * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) - * for more details. + * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). + * In addition to special characters the forward slash is escaped to allow for + * easier `eval` use and `Function` compilation. */ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, reHasRegExpChars = RegExp(reRegExpChars.source); - /** Used to detect functions containing a `this` reference. */ - var reThis = /\bthis\b/; - /** Used to match unescaped characters in compiled string literals. */ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; @@ -153,7 +150,7 @@ 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', - 'window', 'WinRTError' + 'window' ]; /** Used to make template sourceURLs easier to identify. */ @@ -262,8 +259,11 @@ /** Detect free variable `global` from Node.js. */ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + /** Detect free variable `self`. */ + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + /** Detect free variable `window`. */ - var freeWindow = objectTypes[typeof window] && window; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; @@ -274,7 +274,7 @@ * The `this` value is used if it is the global object to avoid Greasemonkey's * restricted `window` object, otherwise the `window` object is used. */ - var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || this; + var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this; /*--------------------------------------------------------------------------*/ @@ -302,6 +302,28 @@ return 0; } + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for callback shorthands and `this` binding. + * + * @private + * @param {Array} array The array to search. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + /** * The base implementation of `_.indexOf` without support for binary searches. * @@ -488,7 +510,6 @@ /** * Gets the index at which the first occurrence of `NaN` is found in `array`. - * If `fromRight` is provided elements of `array` are iterated from right to left. * * @private * @param {Array} array The array to search. @@ -517,7 +538,7 @@ * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ function isObjectLike(value) { - return (value && typeof value == 'object') || false; + return !!value && typeof value == 'object'; } /** @@ -639,19 +660,19 @@ * @returns {Function} Returns a new `lodash` function. * @example * - * _.mixin({ 'add': function(a, b) { return a + b; } }); + * _.mixin({ 'foo': _.constant('foo') }); * * var lodash = _.runInContext(); - * lodash.mixin({ 'sub': function(a, b) { return a - b; } }); + * lodash.mixin({ 'bar': lodash.constant('bar') }); * - * _.isFunction(_.add); + * _.isFunction(_.foo); * // => true - * _.isFunction(_.sub); + * _.isFunction(_.bar); * // => false * - * lodash.isFunction(lodash.add); + * lodash.isFunction(lodash.foo); * // => false - * lodash.isFunction(lodash.sub); + * lodash.isFunction(lodash.bar); * // => true * * // using `context` to mock `Date#getTime` use in `_.now` @@ -704,9 +725,8 @@ var idCounter = 0; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -771,15 +791,17 @@ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; /** - * Used as the maximum length of an array-like value. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) - * for more details. + * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * of an array-like value. */ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; + /** Used to lookup unminified function names. */ + var realNames = {}; + /*------------------------------------------------------------------------*/ /** @@ -929,7 +951,7 @@ * @memberOf _.support * @type boolean */ - support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); + support.funcDecomp = /\bthis\b/.test(function() { return this; }); /** * Detect if `Function#name` is supported (all but IE). @@ -1305,7 +1327,7 @@ /** * A specialized version of `_.forEach` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1326,7 +1348,7 @@ /** * A specialized version of `_.forEachRight` for arrays without support for - * callback shorthands or `this` binding. + * callback shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1346,7 +1368,7 @@ /** * A specialized version of `_.every` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1368,7 +1390,7 @@ /** * A specialized version of `_.filter` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1392,7 +1414,7 @@ /** * A specialized version of `_.map` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1454,7 +1476,7 @@ /** * A specialized version of `_.reduce` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1479,7 +1501,7 @@ /** * A specialized version of `_.reduceRight` for arrays without support for - * callback shorthands or `this` binding. + * callback shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1502,7 +1524,7 @@ /** * A specialized version of `_.some` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. @@ -1522,6 +1544,23 @@ return false; } + /** + * A specialized version of `_.sum` for arrays without support for iteratees. + * + * @private + * @param {Array} array The array to iterate over. + * @returns {number} Returns the sum. + */ + function arraySum(array) { + var length = array.length, + result = 0; + + while (length--) { + result += +array[length] || 0; + } + return result; + } + /** * Used by `_.defaults` to customize its `_.assign` use. * @@ -1636,26 +1675,6 @@ return object; } - /** - * The base implementation of `_.bindAll` without support for individual - * method name arguments. - * - * @private - * @param {Object} object The object to bind and assign the bound methods to. - * @param {string[]} methodNames The object method names to bind. - * @returns {Object} Returns `object`. - */ - function baseBindAll(object, methodNames) { - var index = -1, - length = methodNames.length; - - while (++index < length) { - var key = methodNames[index]; - object[key] = createWrapper(object[key], BIND_FLAG, object); - } - return object; - } - /** * The base implementation of `_.callback` which supports specifying the * number of arguments to provide to `func`. @@ -1669,9 +1688,9 @@ function baseCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function') { - return (typeof thisArg != 'undefined' && isBindable(func)) - ? bindCallback(func, thisArg, argCount) - : func; + return typeof thisArg == 'undefined' + ? func + : bindCallback(func, thisArg, argCount); } if (func == null) { return identity; @@ -1778,14 +1797,14 @@ * @private * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. - * @param {Object} args The `arguments` object to slice and provide to `func`. + * @param {Object} args The arguments provide to `func`. * @returns {number} Returns the timer id. */ - function baseDelay(func, wait, args, fromIndex) { + function baseDelay(func, wait, args) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); + return setTimeout(function() { func.apply(undefined, args); }, wait); } /** @@ -1844,21 +1863,7 @@ * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEach(collection, iteratee) { - var length = collection ? collection.length : 0; - if (!isLength(length)) { - return baseForOwn(collection, iteratee); - } - var index = -1, - iterable = toObject(collection); - - while (++index < length) { - if (iteratee(iterable[index], index, iterable) === false) { - break; - } - } - return collection; - } + var baseEach = createBaseEach(baseForOwn); /** * The base implementation of `_.forEachRight` without support for callback @@ -1869,23 +1874,11 @@ * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ - function baseEachRight(collection, iteratee) { - var length = collection ? collection.length : 0; - if (!isLength(length)) { - return baseForOwnRight(collection, iteratee); - } - var iterable = toObject(collection); - while (length--) { - if (iteratee(iterable[length], length, iterable) === false) { - break; - } - } - return collection; - } + var baseEachRight = createBaseEach(baseForOwnRight, true); /** * The base implementation of `_.every` without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -1934,7 +1927,7 @@ /** * The base implementation of `_.filter` without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -1983,11 +1976,10 @@ * @param {Array} array The array to flatten. * @param {boolean} isDeep Specify a deep flatten. * @param {boolean} isStrict Restrict flattening to arrays and `arguments` objects. - * @param {number} fromIndex The index to start from. * @returns {Array} Returns the new flattened array. */ - function baseFlatten(array, isDeep, isStrict, fromIndex) { - var index = fromIndex - 1, + function baseFlatten(array, isDeep, isStrict) { + var index = -1, length = array.length, resIndex = -1, result = []; @@ -1998,7 +1990,7 @@ if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). - value = baseFlatten(value, isDeep, isStrict, 0); + value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, valLength = value.length; @@ -2026,20 +2018,7 @@ * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseFor(object, iteratee, keysFunc) { - var index = -1, - iterable = toObject(object), - props = keysFunc(object), - length = props.length; - - while (++index < length) { - var key = props[index]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } - } - return object; - } + var baseFor = createBaseFor(); /** * This function is like `baseFor` except that it iterates over properties @@ -2051,19 +2030,7 @@ * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ - function baseForRight(object, iteratee, keysFunc) { - var iterable = toObject(object), - props = keysFunc(object), - length = props.length; - - while (length--) { - var key = props[length]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } - } - return object; - } + var baseForRight = createBaseFor(true); /** * The base implementation of `_.forIn` without support for callback @@ -2128,30 +2095,6 @@ return result; } - /** - * The base implementation of `_.invoke` which requires additional arguments - * to be provided as an array of arguments rather than individually. - * - * @private - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|string} methodName The name of the method to invoke or - * the function invoked per iteration. - * @param {Array} [args] The arguments to invoke the method with. - * @returns {Array} Returns the array of results. - */ - function baseInvoke(collection, methodName, args) { - var index = -1, - isFunc = typeof methodName == 'function', - length = collection ? collection.length : 0, - result = isLength(length) ? Array(length) : []; - - baseEach(collection, function(value) { - var func = isFunc ? methodName : (value != null && value[methodName]); - result[++index] = func ? func.apply(value, args) : undefined; - }); - return result; - } - /** * The base implementation of `_.isEqual` without support for `this` binding * `customizer` functions. @@ -2160,12 +2103,12 @@ * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparing values. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ - function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { // Exit early for identical values. if (value === other) { // Treat `+0` vs. `-0` as not equal. @@ -2180,7 +2123,7 @@ // Return `false` unless both values are `NaN`. return value !== value && other !== other; } - return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB); + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); } /** @@ -2193,12 +2136,12 @@ * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing objects. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ - function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackB) { + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, @@ -2220,21 +2163,27 @@ othIsArr = isTypedArray(other); } } - var objIsObj = objTag == objectTag, - othIsObj = othTag == objectTag, + var objIsObj = (objTag == objectTag || (isLoose && objTag == funcTag)), + othIsObj = (othTag == objectTag || (isLoose && othTag == funcTag)), isSameTag = objTag == othTag; if (isSameTag && !(objIsArr || objIsObj)) { return equalByTag(object, other, objTag); } - var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), - othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + if (isLoose) { + if (!isSameTag && !(objIsObj && othIsObj)) { + return false; + } + } else { + var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - if (valWrapped || othWrapped) { - return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB); - } - if (!isSameTag) { - return false; + if (valWrapped || othWrapped) { + return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + if (!isSameTag) { + return false; + } } // Assume cyclic values are equal. // For more information on detecting circular references see https://es5.github.io/#JO. @@ -2251,7 +2200,7 @@ stackA.push(object); stackB.push(other); - var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isWhere, stackA, stackB); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); stackA.pop(); stackB.pop(); @@ -2261,7 +2210,7 @@ /** * The base implementation of `_.isMatch` without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Object} object The object to inspect. @@ -2272,30 +2221,27 @@ * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, props, values, strictCompareFlags, customizer) { - var length = props.length; - if (object == null) { - return !length; - } var index = -1, + length = props.length, noCustomizer = !customizer; while (++index < length) { if ((noCustomizer && strictCompareFlags[index]) ? values[index] !== object[props[index]] - : !hasOwnProperty.call(object, props[index]) + : !(props[index] in object) ) { return false; } } index = -1; while (++index < length) { - var key = props[index]; - if (noCustomizer && strictCompareFlags[index]) { - var result = hasOwnProperty.call(object, key); - } else { - var objValue = object[key], - srcValue = values[index]; + var key = props[index], + objValue = object[key], + srcValue = values[index]; + if (noCustomizer && strictCompareFlags[index]) { + var result = typeof objValue != 'undefined' || (key in object); + } else { result = customizer ? customizer(objValue, srcValue, key) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(srcValue, objValue, customizer, true); @@ -2310,7 +2256,7 @@ /** * The base implementation of `_.map` without support for callback shorthands - * or `this` binding. + * and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -2336,13 +2282,17 @@ var props = keys(source), length = props.length; + if (!length) { + return constant(true); + } if (length == 1) { var key = props[0], value = source[key]; if (isStrictComparable(value)) { return function(object) { - return object != null && object[key] === value && hasOwnProperty.call(object, key); + return object != null && object[key] === value && + (typeof value != 'undefined' || (key in toObject(object))); }; } } @@ -2355,7 +2305,7 @@ strictCompareFlags[length] = isStrictComparable(value); } return function(object) { - return baseIsMatch(object, props, values, strictCompareFlags); + return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags); }; } @@ -2371,7 +2321,8 @@ function baseMatchesProperty(key, value) { if (isStrictComparable(value)) { return function(object) { - return object != null && object[key] === value; + return object != null && object[key] === value && + (typeof value != 'undefined' || (key in toObject(object))); }; } return function(object) { @@ -2451,7 +2402,7 @@ if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) { result = isArray(value) ? value - : (value ? arrayCopy(value) : []); + : ((value && value.length) ? arrayCopy(value) : []); } else if (isPlainObject(srcValue) || isArguments(srcValue)) { result = isArguments(value) @@ -2488,30 +2439,6 @@ }; } - /** - * The base implementation of `_.pullAt` without support for individual - * index arguments. - * - * @private - * @param {Array} array The array to modify. - * @param {number[]} indexes The indexes of elements to remove. - * @returns {Array} Returns the new array of removed elements. - */ - function basePullAt(array, indexes) { - var length = indexes.length, - result = baseAt(array, indexes); - - indexes.sort(baseCompareAscending); - while (length--) { - var index = parseFloat(indexes[length]); - if (index != previous && isIndex(index)) { - var previous = index; - splice.call(array, index, 1); - } - } - return result; - } - /** * The base implementation of `_.random` without support for argument juggling * and returning floating-point numbers. @@ -2527,7 +2454,7 @@ /** * The base implementation of `_.reduce` and `_.reduceRight` without support - * for callback shorthands or `this` binding, which iterates over `collection` + * for callback shorthands and `this` binding, which iterates over `collection` * using the provided `eachFunc`. * * @private @@ -2594,7 +2521,7 @@ /** * The base implementation of `_.some` without support for callback shorthands - * or `this` binding. + * and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -2661,6 +2588,23 @@ }); } + /** + * The base implementation of `_.sum` without support for callback shorthands + * and `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + /** * The base implementation of `_.uniq` without support for callback shorthands * and `this` binding. @@ -2734,6 +2678,27 @@ return result; } + /** + * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`, + * and `_.takeWhile` without support for callback shorthands and `this` binding. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + /** * The base implementation of `wrapperValue` which returns the result of * performing a sequence of actions on the unwrapped `value`, where each @@ -2742,7 +2707,7 @@ * @private * @param {*} value The unwrapped value. * @param {Array} actions Actions to peform to resolve the unwrapped value. - * @returns {*} Returns the resolved unwrapped value. + * @returns {*} Returns the resolved value. */ function baseWrapperValue(value, actions) { var result = value; @@ -2769,8 +2734,7 @@ * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @param {boolean} [retHighest] Specify returning the highest, instead - * of the lowest, index at which a value should be inserted into `array`. + * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ @@ -2803,8 +2767,7 @@ * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function} iteratee The function invoked per iteration. - * @param {boolean} [retHighest] Specify returning the highest, instead - * of the lowest, index at which a value should be inserted into `array`. + * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ @@ -2970,6 +2933,9 @@ * object composed from the results of running each element in the collection * through an iteratee. * + * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, + * and `_.partition`. + * * @private * @param {Function} setter The function to set keys and values of the accumulator object. * @param {Function} [initializer] The function to initialize the accumulator object. @@ -3001,6 +2967,8 @@ * Creates a function that assigns properties of source object(s) to a given * destination object. * + * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. + * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. @@ -3040,6 +3008,56 @@ }; } + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, + iterable = toObject(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for `_.forIn` or `_.forInRight`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), + props = keysFunc(object), + length = props.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length)) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + /** * Creates a function that wraps `func` and invokes it with the `this` * binding of `thisArg`. @@ -3070,41 +3088,6 @@ return new SetCache(values); }; - /** - * Creates a function to compose other functions into a single function. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new composer function. - */ - function createComposer(fromRight) { - return function() { - var length = arguments.length, - index = length, - fromIndex = fromRight ? (length - 1) : 0; - - if (!length) { - return function() { return arguments[0]; }; - } - var funcs = Array(length); - while (index--) { - funcs[index] = arguments[index]; - if (typeof funcs[index] != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - } - return function() { - var index = fromIndex, - result = funcs[index].apply(this, arguments); - - while ((fromRight ? index-- : ++index < length)) { - result = funcs[index].call(this, result); - } - return result; - }; - }; - } - /** * Creates a function that produces compound words out of the words in a * given string. @@ -3147,7 +3130,26 @@ } /** - * Creates a function that gets the extremum value of a collection. + * Creates a `_.curry` or `_.curryRight` function. + * + * @private + * @param {boolean} flag The curry bit flag. + * @returns {Function} Returns the new curry function. + */ + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = null; + } + var result = createWrapper(func, flag, null, null, null, null, null, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + + /** + * Creates a `_.max` or `_.min` function. * * @private * @param {Function} arrayFunc The function to get the extremum value from an array. @@ -3179,6 +3181,204 @@ }; } + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new find function. + */ + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + } + } + + /** + * Creates a `_.findIndex` or `_.findLastIndex` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new find function. + */ + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + + /** + * Creates a `_.findKey` or `_.findLastKey` function. + * + * @private + * @param {Function} objectFunc The function to iterate over an object. + * @returns {Function} Returns the new find function. + */ + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return function() { + var length = arguments.length; + if (!length) { + return function() { return arguments[0]; }; + } + var wrapper, + index = fromRight ? length : -1, + leftIndex = 0, + funcs = Array(length); + + while ((fromRight ? index-- : ++index < length)) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var funcName = wrapper ? '' : getFuncName(func); + wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper; + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + funcName = getFuncName(func); + + var data = funcName == 'wrapper' ? getData(func) : null; + if (data && isLaziable(data[0])) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments; + if (wrapper && args.length == 1 && isArray(args[0])) { + return wrapper.plant(args[0]).value(); + } + var index = 0, + result = funcs[index].apply(this, args); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + + /** + * Creates a function for `_.forEach` or `_.forEachRight`. + * + * @private + * @param {Function} arrayFunc The function to iterate over an array. + * @param {Function} eachFunc The function to iterate over a collection. + * @returns {Function} Returns the new each function. + */ + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayFunc(collection, iteratee) + : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + + /** + * Creates a function for `_.forIn` or `_.forInRight`. + * + * @private + * @param {Function} objectFunc The function to iterate over an object. + * @returns {Function} Returns the new each function. + */ + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + + /** + * Creates a function for `_.forOwn` or `_.forOwnRight`. + * + * @private + * @param {Function} objectFunc The function to iterate over an object. + * @returns {Function} Returns the new each function. + */ + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + + /** + * Creates a function for `_.padLeft` or `_.padRight`. + * + * @private + * @param {boolean} [fromRight] Specify padding from the right. + * @returns {Function} Returns the new pad function. + */ + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return string && ((fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string)); + }; + } + + /** + * Creates a `_.partial` or `_.partialRight` function. + * + * @private + * @param {boolean} flag The partial bit flag. + * @returns {Function} Returns the new partial function. + */ + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, null, partials, holders); + }); + return partialFunc; + } + + /** + * Creates a function for `_.reduce` or `_.reduceRight`. + * + * @private + * @param {Function} arrayFunc The function to iterate over an array. + * @param {Function} eachFunc The function to iterate over a collection. + * @returns {Function} Returns the new each function. + */ + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayFunc(collection, iteratee, accumulator, initFromArray) + : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + /** * Creates a function that wraps `func` and invokes it with optional `this` * binding of, partial application, and currying. @@ -3242,7 +3442,12 @@ if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } - var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity); + var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity], + result = createHybridWrapper.apply(undefined, newData); + + if (isLaziable(func)) { + setData(result, newData); + } result.placeholder = placeholder; return result; } @@ -3264,9 +3469,8 @@ } /** - * Creates the pad required for `string` based on the given padding length. - * The `chars` string may be truncated if the number of padding characters - * exceeds the padding length. + * Creates the padding required for `string` based on the given `length`. + * The `chars` string is truncated if the number of characters exceeds `length`. * * @private * @param {string} string The string to create padding for. @@ -3274,7 +3478,7 @@ * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the pad for `string`. */ - function createPad(string, length, chars) { + function createPadding(string, length, chars) { var strLength = string.length; length = +length; @@ -3323,6 +3527,22 @@ return wrapper; } + /** + * Creates a `_.sortedIndex` or `_.sortedLastIndex` function. + * + * @private + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {Function} Returns the new index function. + */ + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var func = getCallback(iteratee); + return (func === baseCallback && iteratee == null) + ? binaryIndex(array, value, retHighest) + : binaryIndexBy(array, value, func(iteratee, thisArg, 1), retHighest); + }; + } + /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. @@ -3365,10 +3585,10 @@ partials = holders = null; } - var data = !isBindKey && getData(func), + var data = isBindKey ? null : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; - if (data && data !== true) { + if (data) { mergeData(newData, data); bitmask = newData[1]; arity = newData[9]; @@ -3397,18 +3617,18 @@ * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing arrays. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ - function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stackB) { + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { var index = -1, arrLength = array.length, othLength = other.length, result = true; - if (arrLength != othLength && !(isWhere && othLength > arrLength)) { + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { return false; } // Deep compare the contents, ignoring non-numeric properties. @@ -3418,23 +3638,23 @@ result = undefined; if (customizer) { - result = isWhere + result = isLoose ? customizer(othValue, arrValue, index) : customizer(arrValue, othValue, index); } if (typeof result == 'undefined') { // Recursively compare arrays (susceptible to call stack limits). - if (isWhere) { + if (isLoose) { var othIndex = othLength; while (othIndex--) { othValue = other[othIndex]; - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); if (result) { break; } } } else { - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); } } } @@ -3490,26 +3710,26 @@ * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing values. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ - function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, stackB) { + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; - if (objLength != othLength && !isWhere) { + if (objLength != othLength && !isLoose) { return false; } - var hasCtor, + var skipCtor = isLoose, index = -1; while (++index < objLength) { var key = objProps[index], - result = hasOwnProperty.call(other, key); + result = isLoose ? key in other : hasOwnProperty.call(other, key); if (result) { var objValue = object[key], @@ -3517,21 +3737,21 @@ result = undefined; if (customizer) { - result = isWhere + result = isLoose ? customizer(othValue, objValue, key) : customizer(objValue, othValue, key); } if (typeof result == 'undefined') { // Recursively compare objects (susceptible to call stack limits). - result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB); + result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB); } } if (!result) { return false; } - hasCtor || (hasCtor = key == 'constructor'); + skipCtor || (skipCtor = key == 'constructor'); } - if (!hasCtor) { + if (!skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; @@ -3549,7 +3769,7 @@ /** * Gets the extremum value of `collection` invoking `iteratee` for each value * in `collection` to generate the criterion by which the value is ranked. - * The `iteratee` is invoked with three arguments; (value, index, collection). + * The `iteratee` is invoked with three arguments: (value, index, collection). * * @private * @param {Array|Object|string} collection The collection to iterate over. @@ -3600,6 +3820,37 @@ return metaMap.get(func); }; + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + var getFuncName = (function() { + if (!support.funcNames) { + return constant(''); + } + if (constant.name == 'constant') { + return baseProperty('name'); + } + return function(func) { + var result = func.name, + array = realNames[result], + length = array ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + }; + }()); + /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns @@ -3717,31 +3968,6 @@ return result; } - /** - * Checks if `func` is eligible for `this` binding. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is eligible, else `false`. - */ - function isBindable(func) { - var support = lodash.support, - result = !(support.funcNames ? func.name : support.funcDecomp); - - if (!result) { - var source = fnToString.call(func); - if (!support.funcNames) { - result = !reFuncName.test(source); - } - if (!result) { - // Check if `func` references the `this` keyword and store the result. - result = reThis.test(source) || isNative(func); - baseSetData(func, result); - } - } - return result; - } - /** * Checks if `value` is a valid array-like index. * @@ -3783,12 +4009,22 @@ return false; } + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func); + return !!funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype; + } + /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is based on ES `ToLength`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. + * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). * * @private * @param {*} value The value to check. @@ -3828,22 +4064,13 @@ function mergeData(data, source) { var bitmask = data[1], srcBitmask = source[1], - newBitmask = bitmask | srcBitmask; + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < ARY_FLAG; - var arityFlags = ARY_FLAG | REARG_FLAG, - bindFlags = BIND_FLAG | BIND_KEY_FLAG, - comboFlags = arityFlags | bindFlags | CURRY_BOUND_FLAG | CURRY_RIGHT_FLAG; - - var isAry = bitmask & ARY_FLAG && !(srcBitmask & ARY_FLAG), - isRearg = bitmask & REARG_FLAG && !(srcBitmask & REARG_FLAG), - argPos = (isRearg ? data : source)[7], - ary = (isAry ? data : source)[8]; - - var isCommon = !(bitmask >= REARG_FLAG && srcBitmask > bindFlags) && - !(bitmask > bindFlags && srcBitmask >= REARG_FLAG); - - var isCombo = (newBitmask >= arityFlags && newBitmask <= comboFlags) && - (bitmask < REARG_FLAG || ((isRearg || isAry) && argPos.length <= ary)); + var isCombo = + (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) || + (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) || + (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { @@ -4162,10 +4389,9 @@ * Creates an array excluding all values of the provided arrays using * `SameValueZero` for equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -4178,19 +4404,11 @@ * _.difference([1, 2, 3], [4, 2]); * // => [1, 3] */ - function difference() { - var args = arguments, - index = -1, - length = args.length; - - while (++index < length) { - var value = args[index]; - if (isArray(value) || isArguments(value)) { - break; - } - } - return baseDifference(value, baseFlatten(args, false, true, ++index)); - } + var difference = restParam(function(array, values) { + return (isArray(array) || isArguments(array)) + ? baseDifference(array, baseFlatten(values, false, true)) + : []; + }); /** * Creates a slice of `array` with `n` elements dropped from the beginning. @@ -4266,7 +4484,7 @@ /** * Creates a slice of `array` excluding elements dropped from the end. * Elements are dropped until `predicate` returns falsey. The predicate is - * bound to `thisArg` and invoked with three arguments; (value, index, array). + * bound to `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -4313,19 +4531,15 @@ * // => ['barney', 'fred', 'pebbles'] */ function dropRightWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - predicate = getCallback(predicate, thisArg, 3); - while (length-- && predicate(array[length], length, array)) {} - return baseSlice(array, 0, length + 1); + return (array && array.length) + ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) + : []; } /** * Creates a slice of `array` excluding elements dropped from the beginning. * Elements are dropped until `predicate` returns falsey. The predicate is - * bound to `thisArg` and invoked with three arguments; (value, index, array). + * bound to `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -4372,14 +4586,9 @@ * // => ['barney', 'fred', 'pebbles'] */ function dropWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - var index = -1; - predicate = getCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) {} - return baseSlice(array, index); + return (array && array.length) + ? baseWhile(array, getCallback(predicate, thisArg, 3), true) + : []; } /** @@ -4396,6 +4605,19 @@ * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8], '*', 1, 2); + * // => [4, '*', 8] */ function fill(array, value, start, end) { var length = array ? array.length : 0; @@ -4411,7 +4633,7 @@ /** * This method is like `_.find` except that it returns the index of the first - * element `predicate` returns truthy for, instead of the element itself. + * element `predicate` returns truthy for instead of the element itself. * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -4457,18 +4679,7 @@ * _.findIndex(users, 'active'); * // => 2 */ - function findIndex(array, predicate, thisArg) { - var index = -1, - length = array ? array.length : 0; - - predicate = getCallback(predicate, thisArg, 3); - while (++index < length) { - if (predicate(array[index], index, array)) { - return index; - } - } - return -1; - } + var findIndex = createFindIndex(); /** * This method is like `_.findIndex` except that it iterates over elements @@ -4518,16 +4729,7 @@ * _.findLastIndex(users, 'active'); * // => 0 */ - function findLastIndex(array, predicate, thisArg) { - var length = array ? array.length : 0; - predicate = getCallback(predicate, thisArg, 3); - while (length--) { - if (predicate(array[length], length, array)) { - return length; - } - } - return -1; - } + var findLastIndex = createFindIndex(true); /** * Gets the first element of `array`. @@ -4564,18 +4766,18 @@ * @example * * _.flatten([1, [2, 3, [4]]]); - * // => [1, 2, 3, [4]]; + * // => [1, 2, 3, [4]] * * // using `isDeep` * _.flatten([1, [2, 3, [4]]], true); - * // => [1, 2, 3, 4]; + * // => [1, 2, 3, 4] */ function flatten(array, isDeep, guard) { var length = array ? array.length : 0; if (guard && isIterateeCall(array, isDeep, guard)) { isDeep = false; } - return length ? baseFlatten(array, isDeep, false, 0) : []; + return length ? baseFlatten(array, isDeep) : []; } /** @@ -4589,11 +4791,11 @@ * @example * * _.flattenDeep([1, [2, 3, [4]]]); - * // => [1, 2, 3, 4]; + * // => [1, 2, 3, 4] */ function flattenDeep(array) { var length = array ? array.length : 0; - return length ? baseFlatten(array, true, false, 0) : []; + return length ? baseFlatten(array, true) : []; } /** @@ -4602,10 +4804,9 @@ * it is used as the offset from the end of `array`. If `array` is sorted * providing `true` for `fromIndex` performs a faster binary search. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -4668,10 +4869,9 @@ * Creates an array of unique values in all provided arrays using `SameValueZero` * for equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -4799,10 +4999,10 @@ * comparisons. * * **Notes:** - * - Unlike `_.without`, this method mutates `array`. - * - `SameValueZero` comparisons are like strict equality comparisons, e.g. `===`, - * except that `NaN` matches `NaN`. See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * - Unlike `_.without`, this method mutates `array` + * - [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except + * that `NaN` matches `NaN` * * @static * @memberOf _ @@ -4865,14 +5065,28 @@ * console.log(evens); * // => [10, 20] */ - function pullAt(array) { - return basePullAt(array || [], baseFlatten(arguments, false, false, 1)); - } + var pullAt = restParam(function(array, indexes) { + array || (array = []); + indexes = baseFlatten(indexes); + + var length = indexes.length, + result = baseAt(array, indexes); + + indexes.sort(baseCompareAscending); + while (length--) { + var index = parseFloat(indexes[length]); + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return result; + }); /** * Removes all elements from `array` that `predicate` returns truthy for * and returns an array of the removed elements. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). + * `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -4976,14 +5190,14 @@ * to compute their sort ranking. The iteratee is bound to `thisArg` and * invoked with one argument; (value). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -5017,12 +5231,7 @@ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ - function sortedIndex(array, value, iteratee, thisArg) { - var func = getCallback(iteratee); - return (func === baseCallback && iteratee == null) - ? binaryIndex(array, value) - : binaryIndexBy(array, value, func(iteratee, thisArg, 1)); - } + var sortedIndex = createSortedIndex(); /** * This method is like `_.sortedIndex` except that it returns the highest @@ -5044,12 +5253,7 @@ * _.sortedLastIndex([4, 4, 5, 5], 5); * // => 4 */ - function sortedLastIndex(array, value, iteratee, thisArg) { - var func = getCallback(iteratee); - return (func === baseCallback && iteratee == null) - ? binaryIndex(array, value, true) - : binaryIndexBy(array, value, func(iteratee, thisArg, 1), true); - } + var sortedLastIndex = createSortedIndex(true); /** * Creates a slice of `array` with `n` elements taken from the beginning. @@ -5125,7 +5329,7 @@ /** * Creates a slice of `array` with elements taken from the end. Elements are * taken until `predicate` returns falsey. The predicate is bound to `thisArg` - * and invoked with three arguments; (value, index, array). + * and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -5172,19 +5376,15 @@ * // => [] */ function takeRightWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - predicate = getCallback(predicate, thisArg, 3); - while (length-- && predicate(array[length], length, array)) {} - return baseSlice(array, length + 1); + return (array && array.length) + ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) + : []; } /** * Creates a slice of `array` with elements taken from the beginning. Elements * are taken until `predicate` returns falsey. The predicate is bound to - * `thisArg` and invoked with three arguments; (value, index, array). + * `thisArg` and invoked with three arguments: (value, index, array). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -5231,24 +5431,18 @@ * // => [] */ function takeWhile(array, predicate, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - var index = -1; - predicate = getCallback(predicate, thisArg, 3); - while (++index < length && predicate(array[index], index, array)) {} - return baseSlice(array, 0, index); + return (array && array.length) + ? baseWhile(array, getCallback(predicate, thisArg, 3)) + : []; } /** * Creates an array of unique values, in order, of the provided arrays using * `SameValueZero` for equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -5260,9 +5454,9 @@ * _.union([1, 2], [4, 2], [2, 1]); * // => [1, 2, 4] */ - function union() { - return baseUniq(baseFlatten(arguments, false, true, 0)); - } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); /** * Creates a duplicate-value-free version of an array using `SameValueZero` @@ -5270,23 +5464,22 @@ * search algorithm for sorted arrays. If an iteratee function is provided it * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked - * with three arguments; (value, index, array). + * with three arguments: (value, index, array). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -5368,10 +5561,9 @@ * Creates an array excluding all provided values using `SameValueZero` for * equality comparisons. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -5384,14 +5576,15 @@ * _.without([1, 2, 1, 3], 1, 2); * // => [3] */ - function without(array) { - return baseDifference(array, baseSlice(arguments, 1)); - } + var without = restParam(function(array, values) { + return (isArray(array) || isArguments(array)) + ? baseDifference(array, values) + : []; + }); /** - * Creates an array that is the symmetric difference of the provided arrays. - * See [Wikipedia](https://en.wikipedia.org/wiki/Symmetric_difference) for - * more details. + * Creates an array that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the provided arrays. * * @static * @memberOf _ @@ -5433,20 +5626,13 @@ * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] */ - function zip() { - var length = arguments.length, - array = Array(length); - - while (length--) { - array[length] = arguments[length]; - } - return unzip(array); - } + var zip = restParam(unzip); /** - * Creates an object composed from arrays of property names and values. Provide - * either a single two dimensional array, e.g. `[[key1, value1], [key2, value2]]` - * or two arrays, one of property names and one of corresponding values. + * The inverse of `_.pairs`; this method returns an object composed from arrays + * of property names and values. Provide either a single two dimensional array, + * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names + * and one of corresponding values. * * @static * @memberOf _ @@ -5457,6 +5643,9 @@ * @returns {Object} Returns the new object. * @example * + * _.zipObject([['fred', 30], ['barney', 40]]); + * // => { 'fred': 30, 'barney': 40 } + * * _.zipObject(['fred', 'barney'], [30, 40]); * // => { 'fred': 30, 'barney': 40 } */ @@ -5553,13 +5742,14 @@ * @returns {*} Returns the result of `interceptor`. * @example * - * _([1, 2, 3]) - * .last() + * _(' abc ') + * .chain() + * .trim() * .thru(function(value) { * return [value]; * }) * .value(); - * // => [3] + * // => ['abc'] */ function thru(value, interceptor, thisArg) { return interceptor.call(thisArg, value); @@ -5749,32 +5939,32 @@ * _.at(['a', 'b', 'c'], [0, 2]); * // => ['a', 'c'] * - * _.at(['fred', 'barney', 'pebbles'], 0, 2); - * // => ['fred', 'pebbles'] + * _.at(['barney', 'fred', 'pebbles'], 0, 2); + * // => ['barney', 'pebbles'] */ - function at(collection) { + var at = restParam(function(collection, props) { var length = collection ? collection.length : 0; if (isLength(length)) { collection = toIterable(collection); } - return baseAt(collection, baseFlatten(arguments, false, false, 1)); - } + return baseAt(collection, baseFlatten(props)); + }); /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the number of times the key was returned by `iteratee`. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -5807,7 +5997,7 @@ /** * Checks if `predicate` returns truthy for **all** elements of `collection`. - * The predicate is bound to `thisArg` and invoked with three arguments; + * The predicate is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` @@ -5855,6 +6045,9 @@ */ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = null; + } if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } @@ -5864,7 +6057,7 @@ /** * Iterates over elements of `collection`, returning an array of all elements * `predicate` returns truthy for. The predicate is bound to `thisArg` and - * invoked with three arguments; (value, index|key, collection). + * invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -5919,7 +6112,7 @@ /** * Iterates over elements of `collection`, returning the first element * `predicate` returns truthy for. The predicate is bound to `thisArg` and - * invoked with three arguments; (value, index|key, collection). + * invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -5966,14 +6159,7 @@ * _.result(_.find(users, 'active'), 'user'); * // => 'barney' */ - function find(collection, predicate, thisArg) { - if (isArray(collection)) { - var index = findIndex(collection, predicate, thisArg); - return index > -1 ? collection[index] : undefined; - } - predicate = getCallback(predicate, thisArg, 3); - return baseFind(collection, predicate, baseEach); - } + var find = createFind(baseEach); /** * This method is like `_.find` except that it iterates over elements of @@ -5994,10 +6180,7 @@ * }); * // => 3 */ - function findLast(collection, predicate, thisArg) { - predicate = getCallback(predicate, thisArg, 3); - return baseFind(collection, predicate, baseEachRight); - } + var findLast = createFind(baseEachRight, true); /** * Performs a deep comparison between each element in `collection` and the @@ -6034,7 +6217,7 @@ /** * Iterates over elements of `collection` invoking `iteratee` for each element. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * @@ -6062,11 +6245,7 @@ * }); * // => logs each value-key pair and returns the object (iteration order is not guaranteed) */ - function forEach(collection, iteratee, thisArg) { - return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEach(collection, iteratee) - : baseEach(collection, bindCallback(iteratee, thisArg, 3)); - } + var forEach = createForEach(arrayEach, baseEach); /** * This method is like `_.forEach` except that it iterates over elements of @@ -6084,30 +6263,26 @@ * * _([1, 2]).forEachRight(function(n) { * console.log(n); - * }).join(','); + * }).value(); * // => logs each value from right to left and returns the array */ - function forEachRight(collection, iteratee, thisArg) { - return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) - ? arrayEachRight(collection, iteratee) - : baseEachRight(collection, bindCallback(iteratee, thisArg, 3)); - } + var forEachRight = createForEach(arrayEachRight, baseEachRight); /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is an array of the elements responsible for generating the key. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -6148,10 +6323,9 @@ * comparisons. If `fromIndex` is negative, it is used as the offset from * the end of `collection`. * - * **Note:** `SameValueZero` comparisons are like strict equality comparisons, - * e.g. `===`, except that `NaN` matches `NaN`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) - * for more details. + * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * comparisons are like strict equality comparisons, e.g. `===`, except that + * `NaN` matches `NaN`. * * @static * @memberOf _ @@ -6160,6 +6334,7 @@ * @param {Array|Object|string} collection The collection to search. * @param {*} target The value to search for. * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {boolean} Returns `true` if a matching element is found, else `false`. * @example * @@ -6175,7 +6350,7 @@ * _.includes('pebbles', 'eb'); * // => true */ - function includes(collection, target, fromIndex) { + function includes(collection, target, fromIndex, guard) { var length = collection ? collection.length : 0; if (!isLength(length)) { collection = values(collection); @@ -6184,10 +6359,10 @@ if (!length) { return false; } - if (typeof fromIndex == 'number') { - fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); - } else { + if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) @@ -6198,17 +6373,17 @@ * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The - * iteratee function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -6266,23 +6441,32 @@ * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ - function invoke(collection, methodName) { - return baseInvoke(collection, methodName, baseSlice(arguments, 2)); - } + var invoke = restParam(function(collection, methodName, args) { + var index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = isLength(length) ? Array(length) : []; + + baseEach(collection, function(value) { + var func = isFunc ? methodName : (value != null && value[methodName]); + result[++index] = func ? func.apply(value, args) : undefined; + }); + return result; + }); /** * Creates an array of values by running each element in `collection` through * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three - * arguments; (value, index|key, collection). + * arguments: (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -6291,9 +6475,9 @@ * * The guarded methods are: * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, `drop`, - * `dropRight`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`, `slice`, - * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`, `trimRight`, - * `trunc`, `random`, `range`, `sample`, `uniq`, and `words` + * `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`, + * `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`, + * `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, `uniq`, and `words` * * @static * @memberOf _ @@ -6336,7 +6520,7 @@ * Creates an array of elements split into two groups, the first of which * contains elements `predicate` returns truthy for, while the second of which * contains elements `predicate` returns falsey for. The predicate is bound - * to `thisArg` and invoked with three arguments; (value, index|key, collection). + * to `thisArg` and invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -6427,14 +6611,14 @@ * each element in `collection` through `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of `collection` is used as the initial - * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; + * value. The `iteratee` is bound to `thisArg` and invoked with four arguments: * (accumulator, value, index|key, collection). * * Many lodash methods are guarded to work as interatees for methods like * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: - * `assign`, `defaults`, `merge`, and `sortAllBy` + * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` * * @static * @memberOf _ @@ -6458,10 +6642,7 @@ * }, {}); * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed) */ - function reduce(collection, iteratee, accumulator, thisArg) { - var func = isArray(collection) ? arrayReduce : baseReduce; - return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); - } + var reduce = createReduce(arrayReduce, baseEach); /** * This method is like `_.reduce` except that it iterates over elements of @@ -6485,10 +6666,7 @@ * }, []); * // => [4, 5, 2, 3, 0, 1] */ - function reduceRight(collection, iteratee, accumulator, thisArg) { - var func = isArray(collection) ? arrayReduceRight : baseReduce; - return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); - } + var reduceRight = createReduce(arrayReduceRight, baseEachRight); /** * The opposite of `_.filter`; this method returns the elements of `collection` @@ -6575,9 +6753,8 @@ } /** - * Creates an array of shuffled values, using a version of the Fisher-Yates - * shuffle. See [Wikipedia](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle) - * for more details. + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). * * @static * @memberOf _ @@ -6635,7 +6812,7 @@ * Checks if `predicate` returns truthy for **any** element of `collection`. * The function returns as soon as it finds a passing value and does not iterate * over the entire collection. The predicate is bound to `thisArg` and invoked - * with three arguments; (value, index|key, collection). + * with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -6682,6 +6859,9 @@ */ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = null; + } if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } @@ -6692,17 +6872,17 @@ * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. - * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -6778,17 +6958,24 @@ * _.map(_.sortByAll(users, ['user', 'age']), _.values); * // => [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ - function sortByAll(collection) { + function sortByAll() { + var args = arguments, + collection = args[0], + guard = args[3], + index = 0, + length = args.length - 1; + if (collection == null) { return []; } - var args = arguments, - guard = args[3]; - - if (guard && isIterateeCall(args[1], args[2], guard)) { - args = [collection, args[1]]; + var props = Array(length); + while (index < length) { + props[index] = args[++index]; } - return baseSortByOrder(collection, baseFlatten(args, false, false, 1), []); + if (guard && isIterateeCall(args[1], args[2], guard)) { + props = args[1]; + } + return baseSortByOrder(collection, baseFlatten(props), []); } /** @@ -7007,7 +7194,7 @@ * @category Function * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * @@ -7026,16 +7213,14 @@ * bound('hi'); * // => 'hi fred!' */ - function bind(func, thisArg) { + var bind = restParam(function(func, thisArg, partials) { var bitmask = BIND_FLAG; - if (arguments.length > 2) { - var partials = baseSlice(arguments, 2), - holders = replaceHolders(partials, bind.placeholder); - + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(func, bitmask, thisArg, partials, holders); - } + }); /** * Binds methods of an object to the object itself, overwriting the existing @@ -7065,13 +7250,18 @@ * jQuery('#docs').on('click', view.onClick); * // => logs 'clicked docs' when the element is clicked */ - function bindAll(object) { - return baseBindAll(object, - arguments.length > 1 - ? baseFlatten(arguments, false, false, 1) - : functions(object) - ); - } + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + + var index = -1, + length = methodNames.length; + + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); /** * Creates a function that invokes the method at `object[key]` and prepends @@ -7090,7 +7280,7 @@ * @category Function * @param {Object} object The object the method belongs to. * @param {string} key The key of the method. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * @@ -7117,16 +7307,14 @@ * bound('hi'); * // => 'hiya fred!' */ - function bindKey(object, key) { + var bindKey = restParam(function(object, key, partials) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; - if (arguments.length > 2) { - var partials = baseSlice(arguments, 2), - holders = replaceHolders(partials, bindKey.placeholder); - + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(key, bitmask, object, partials, holders); - } + }); /** * Creates a function that accepts one or more arguments of `func` that when @@ -7168,14 +7356,7 @@ * curried(1)(_, 3)(2); * // => [1, 2, 3] */ - function curry(func, arity, guard) { - if (guard && isIterateeCall(func, arity, guard)) { - arity = null; - } - var result = createWrapper(func, CURRY_FLAG, null, null, null, null, null, arity); - result.placeholder = curry.placeholder; - return result; - } + var curry = createCurry(CURRY_FLAG); /** * This method is like `_.curry` except that arguments are applied to `func` @@ -7214,14 +7395,7 @@ * curried(3)(1, _)(2); * // => [1, 2, 3] */ - function curryRight(func, arity, guard) { - if (guard && isIterateeCall(func, arity, guard)) { - arity = null; - } - var result = createWrapper(func, CURRY_RIGHT_FLAG, null, null, null, null, null, arity); - result.placeholder = curryRight.placeholder; - return result; - } + var curryRight = createCurry(CURRY_RIGHT_FLAG); /** * Creates a function that delays invoking `func` until after `wait` milliseconds @@ -7416,9 +7590,9 @@ * }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ - function defer(func) { - return baseDelay(func, 1, arguments, 1); - } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); /** * Invokes `func` after `wait` milliseconds. Any additional arguments are @@ -7438,9 +7612,9 @@ * }, 1000, 'later'); * // => logs 'later' after one second */ - function delay(func, wait) { - return baseDelay(func, wait, arguments, 2); - } + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); /** * Creates a function that returns the result of invoking the provided @@ -7462,7 +7636,7 @@ * addSquare(1, 2); * // => 9 */ - var flow = createComposer(); + var flow = createFlow(); /** * This method is like `_.flow` except that it creates a function that @@ -7484,7 +7658,7 @@ * addSquare(1, 2); * // => 9 */ - var flowRight = createComposer(true); + var flowRight = createFlow(true); /** * Creates a function that memoizes the result of `func`. If `resolver` is @@ -7496,10 +7670,8 @@ * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the ES `Map` method interface - * of `get`, `has`, and `set`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) - * for more details. + * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * method interface of `get`, `has`, and `set`. * * @static * @memberOf _ @@ -7590,7 +7762,7 @@ /** * Creates a function that is restricted to invoking `func` once. Repeat calls * to the function return the value of the first call. The `func` is invoked - * with the `this` binding of the created function. + * with the `this` binding and arguments of the created function. * * @static * @memberOf _ @@ -7623,7 +7795,7 @@ * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * @@ -7640,12 +7812,7 @@ * greetFred('hi'); * // => 'hi fred' */ - function partial(func) { - var partials = baseSlice(arguments, 1), - holders = replaceHolders(partials, partial.placeholder); - - return createWrapper(func, PARTIAL_FLAG, null, partials, holders); - } + var partial = createPartial(PARTIAL_FLAG); /** * This method is like `_.partial` except that partially applied arguments @@ -7661,7 +7828,7 @@ * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. - * @param {...*} [args] The arguments to be partially applied. + * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * @@ -7678,12 +7845,7 @@ * sayHelloTo('fred'); * // => 'hello fred' */ - function partialRight(func) { - var partials = baseSlice(arguments, 1), - holders = replaceHolders(partials, partialRight.placeholder); - - return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders); - } + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); /** * Creates a function that invokes `func` with arguments arranged according @@ -7713,29 +7875,80 @@ * }, [1, 2, 3]); * // => [3, 6, 9] */ - function rearg(func) { - var indexes = baseFlatten(arguments, false, false, 1); - return createWrapper(func, REARG_FLAG, null, null, null, indexes); - } + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes)); + }); /** * Creates a function that invokes `func` with the `this` binding of the - * created function and the array of arguments provided to the created - * function much like [Function#apply](http://es5.github.io/#x15.3.4.3). + * created function and arguments from `start` and beyond provided as an array. + * + * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters). + * + * @static + * @memberOf _ + * @category Function + * @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. + * @example + * + * var say = _.restParam(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function restParam(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(typeof start == 'undefined' ? (func.length - 1) : (+start || 0), 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + rest = Array(length); + + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: return func.call(this, rest); + case 1: return func.call(this, args[0], rest); + case 2: return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of the created + * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3). + * + * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). * * @static * @memberOf _ * @category Function * @param {Function} func The function to spread arguments over. - * @returns {*} Returns the new function. + * @returns {Function} Returns the new function. * @example * - * var spread = _.spread(function(who, what) { + * var say = _.spread(function(who, what) { * return who + ' says ' + what; * }); * - * spread(['Fred', 'hello']); - * // => 'Fred says hello' + * say(['fred', 'hello']); + * // => 'fred says hello' * * // with a Promise * var numbers = Promise.all([ @@ -7850,12 +8063,12 @@ * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value [, index|key, object]). * - * **Note:** This method is loosely based on the structured clone algorithm. + * **Note:** This method is loosely based on the + * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, - * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) - * for more details. + * Maps, Sets, and WeakMaps. * * @static * @memberOf _ @@ -7913,12 +8126,12 @@ * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value [, index|key, object]). * - * **Note:** This method is loosely based on the structured clone algorithm. + * **Note:** This method is loosely based on the + * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, - * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) - * for more details. + * Maps, Sets, and WeakMaps. * * @static * @memberOf _ @@ -7975,7 +8188,7 @@ */ function isArguments(value) { var length = isObjectLike(value) ? value.length : undefined; - return (isLength(length) && objToString.call(value) == argsTag) || false; + return isLength(length) && objToString.call(value) == argsTag; } /** @@ -7995,7 +8208,7 @@ * // => false */ var isArray = nativeIsArray || function(value) { - return (isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag) || false; + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; }; /** @@ -8015,7 +8228,7 @@ * // => false */ function isBoolean(value) { - return (value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag) || false; + return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag); } /** @@ -8035,7 +8248,7 @@ * // => false */ function isDate(value) { - return (isObjectLike(value) && objToString.call(value) == dateTag) || false; + return isObjectLike(value) && objToString.call(value) == dateTag; } /** @@ -8055,13 +8268,13 @@ * // => false */ function isElement(value) { - return (value && value.nodeType === 1 && isObjectLike(value) && - (objToString.call(value).indexOf('Element') > -1)) || false; + return !!value && value.nodeType === 1 && isObjectLike(value) && + (objToString.call(value).indexOf('Element') > -1); } // Fallback for environments without DOM support. if (!support.dom) { isElement = function(value) { - return (value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value)) || false; + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); }; } @@ -8109,7 +8322,7 @@ * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three - * arguments; (value, other [, index|key]). + * arguments: (value, other [, index|key]). * * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Objects are compared by @@ -8174,15 +8387,13 @@ * // => false */ function isError(value) { - return (isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag) || false; + return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag; } /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on ES `Number.isFinite`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) - * for more details. + * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). * * @static * @memberOf _ @@ -8234,11 +8445,9 @@ }; /** - * Checks if `value` is the language type of `Object`. + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * **Note:** See the [ES5 spec](https://es5.github.io/#x8) for more details. - * * @static * @memberOf _ * @category Lang @@ -8259,7 +8468,7 @@ // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; - return type == 'function' || (value && type == 'object') || false; + return type == 'function' || (!!value && type == 'object'); } /** @@ -8267,7 +8476,7 @@ * `object` contains equivalent property values. If `customizer` is provided * it is invoked to compare values. If `customizer` returns `undefined` * comparisons are handled by the method instead. The `customizer` is bound - * to `thisArg` and invoked with three arguments; (value, other, index|key). + * to `thisArg` and invoked with three arguments: (value, other, index|key). * * **Note:** This method supports comparing properties of arrays, booleans, * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions @@ -8305,13 +8514,19 @@ var props = keys(source), length = props.length; + if (!length) { + return true; + } + if (object == null) { + return false; + } customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); if (!customizer && length == 1) { var key = props[0], value = source[key]; if (isStrictComparable(value)) { - return object != null && value === object[key] && hasOwnProperty.call(object, key); + return value === object[key] && (typeof value != 'undefined' || (key in toObject(object))); } } var values = Array(length), @@ -8321,15 +8536,14 @@ value = values[length] = source[props[length]]; strictCompareFlags[length] = isStrictComparable(value); } - return baseIsMatch(object, props, values, strictCompareFlags, customizer); + return baseIsMatch(toObject(object), props, values, strictCompareFlags, customizer); } /** * Checks if `value` is `NaN`. * - * **Note:** This method is not the same as native `isNaN` which returns `true` - * for `undefined` and other non-numeric values. See the [ES5 spec](https://es5.github.io/#x15.1.2.4) - * for more details. + * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4) + * which returns `true` for `undefined` and other non-numeric values. * * @static * @memberOf _ @@ -8379,7 +8593,7 @@ if (objToString.call(value) == funcTag) { return reNative.test(fnToString.call(value)); } - return (isObjectLike(value) && reHostCtor.test(value)) || false; + return isObjectLike(value) && reHostCtor.test(value); } /** @@ -8425,7 +8639,7 @@ * // => false */ function isNumber(value) { - return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag) || false; + return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag); } /** @@ -8507,7 +8721,7 @@ * // => false */ function isString(value) { - return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag) || false; + return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag); } /** @@ -8527,7 +8741,7 @@ * // => false */ function isTypedArray(value) { - return (isObjectLike(value) && isLength(value.length) && typedArrayTags[objToString.call(value)]) || false; + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; } /** @@ -8609,7 +8823,7 @@ * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. * If `customizer` is provided it is invoked to produce the assigned values. - * The `customizer` is bound to `thisArg` and invoked with five arguments; + * The `customizer` is bound to `thisArg` and invoked with five arguments: * (objectValue, sourceValue, key, object, source). * * @static @@ -8694,18 +8908,18 @@ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ - function defaults(object) { + var defaults = restParam(function(args) { + var object = args[0]; if (object == null) { return object; } - var args = arrayCopy(arguments); args.push(assignDefaults); return assign.apply(undefined, args); - } + }); /** - * This method is like `_.findIndex` except that it returns the key of the - * first element `predicate` returns truthy for, instead of the element itself. + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -8751,10 +8965,7 @@ * _.findKey(users, 'active'); * // => 'barney' */ - function findKey(object, predicate, thisArg) { - predicate = getCallback(predicate, thisArg, 3); - return baseFind(object, predicate, baseForOwn, true); - } + var findKey = createFindKey(baseForOwn); /** * This method is like `_.findKey` except that it iterates over elements of @@ -8804,15 +9015,12 @@ * _.findLastKey(users, 'active'); * // => 'pebbles' */ - function findLastKey(object, predicate, thisArg) { - predicate = getCallback(predicate, thisArg, 3); - return baseFind(object, predicate, baseForOwnRight, true); - } + var findLastKey = createFindKey(baseForOwnRight); /** * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked - * with three arguments; (value, key, object). Iterator functions may exit + * with three arguments: (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * * @static @@ -8836,12 +9044,7 @@ * }); * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed) */ - function forIn(object, iteratee, thisArg) { - if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { - iteratee = bindCallback(iteratee, thisArg, 3); - } - return baseFor(object, iteratee, keysIn); - } + var forIn = createForIn(baseFor); /** * This method is like `_.forIn` except that it iterates over properties of @@ -8868,15 +9071,12 @@ * }); * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c' */ - function forInRight(object, iteratee, thisArg) { - iteratee = bindCallback(iteratee, thisArg, 3); - return baseForRight(object, iteratee, keysIn); - } + var forInRight = createForIn(baseForRight); /** * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with - * three arguments; (value, key, object). Iterator functions may exit iteration + * three arguments: (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * * @static @@ -8900,12 +9100,7 @@ * }); * // => logs 'a' and 'b' (iteration order is not guaranteed) */ - function forOwn(object, iteratee, thisArg) { - if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { - iteratee = bindCallback(iteratee, thisArg, 3); - } - return baseForOwn(object, iteratee); - } + var forOwn = createForOwn(baseForOwn); /** * This method is like `_.forOwn` except that it iterates over properties of @@ -8932,10 +9127,7 @@ * }); * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b' */ - function forOwnRight(object, iteratee, thisArg) { - iteratee = bindCallback(iteratee, thisArg, 3); - return baseForRight(object, iteratee, keys); - } + var forOwnRight = createForOwn(baseForOwnRight); /** * Creates an array of function property names from all enumerable properties, @@ -9120,7 +9312,7 @@ /** * Creates an object with the same keys as `object` and values generated by * running each own enumerable property of `object` through `iteratee`. The - * iteratee function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments: * (value, key, object). * * If a property name is provided for `iteratee` the created `_.property` @@ -9175,7 +9367,7 @@ * provided it is invoked to produce the merged values of the destination and * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked - * with five arguments; (objectValue, sourceValue, key, object, source). + * with five arguments: (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ @@ -9224,7 +9416,7 @@ * Property names may be specified as individual arguments or as arrays of * property names. If `predicate` is provided it is invoked for each property * of `object` omitting the properties `predicate` returns truthy for. The - * predicate is bound to `thisArg` and invoked with three arguments; + * predicate is bound to `thisArg` and invoked with three arguments: * (value, key, object). * * @static @@ -9246,19 +9438,19 @@ * _.omit(object, _.isNumber); * // => { 'user': 'fred' } */ - function omit(object, predicate, thisArg) { + var omit = restParam(function(object, props) { if (object == null) { return {}; } - if (typeof predicate != 'function') { - var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + if (typeof props[0] != 'function') { + var props = arrayMap(baseFlatten(props), String); return pickByArray(object, baseDifference(keysIn(object), props)); } - predicate = bindCallback(predicate, thisArg, 3); + var predicate = bindCallback(props[0], props[1], 3); return pickByCallback(object, function(value, key, object) { return !predicate(value, key, object); }); - } + }); /** * Creates a two dimensional array of the key-value pairs for `object`, @@ -9292,7 +9484,7 @@ * names may be specified as individual arguments or as arrays of property * names. If `predicate` is provided it is invoked for each property of `object` * picking the properties `predicate` returns truthy for. The predicate is - * bound to `thisArg` and invoked with three arguments; (value, key, object). + * bound to `thisArg` and invoked with three arguments: (value, key, object). * * @static * @memberOf _ @@ -9313,14 +9505,14 @@ * _.pick(object, _.isString); * // => { 'user': 'fred' } */ - function pick(object, predicate, thisArg) { + var pick = restParam(function(object, props) { if (object == null) { return {}; } - return typeof predicate == 'function' - ? pickByCallback(object, bindCallback(predicate, thisArg, 3)) - : pickByArray(object, baseFlatten(arguments, false, false, 1)); - } + return typeof props[0] == 'function' + ? pickByCallback(object, bindCallback(props[0], props[1], 3)) + : pickByArray(object, baseFlatten(props)); + }); /** * Resolves the value of property `key` on `object`. If the value of `key` is @@ -9365,7 +9557,7 @@ * `accumulator` object which is the result of running each of its own enumerable * properties through `iteratee`, with each invocation potentially mutating * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked - * with four arguments; (accumulator, value, key, object). Iterator functions + * with four arguments: (accumulator, value, key, object). Iterator functions * may exit iteration early by explicitly returning `false`. * * @static @@ -9576,8 +9768,7 @@ /*------------------------------------------------------------------------*/ /** - * Converts `string` to camel case. - * See [Wikipedia](https://en.wikipedia.org/wiki/CamelCase) for more details. + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). * * @static * @memberOf _ @@ -9619,9 +9810,8 @@ } /** - * Deburrs `string` by converting latin-1 supplementary letters to basic latin letters. - * See [Wikipedia](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * for more details. + * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). * * @static * @memberOf _ @@ -9635,7 +9825,7 @@ */ function deburr(string) { string = baseToString(string); - return string && string.replace(reLatin1, deburrLetter); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMarks, ''); } /** @@ -9690,9 +9880,8 @@ * [#108](https://html5sec.org/#108), and [#133](https://html5sec.org/#133) of * the [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. * - * When working with HTML you should always quote attribute values to reduce - * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) - * for more details. + * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping) + * to reduce XSS vectors. * * @static * @memberOf _ @@ -9713,8 +9902,8 @@ } /** - * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", - * "+", "(", ")", "[", "]", "{" and "}" in `string`. + * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?", + * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ @@ -9724,7 +9913,7 @@ * @example * * _.escapeRegExp('[lodash](https://lodash.com/)'); - * // => '\[lodash\]\(https://lodash\.com/\)' + * // => '\[lodash\]\(https:\/\/lodash\.com\/\)' */ function escapeRegExp(string) { string = baseToString(string); @@ -9734,9 +9923,7 @@ } /** - * Converts `string` to kebab case. - * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles) for - * more details. + * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). * * @static * @memberOf _ @@ -9759,9 +9946,8 @@ }); /** - * Pads `string` on the left and right sides if it is shorter then the given - * padding length. The `chars` string may be truncated if the number of padding - * characters can't be evenly divided by the padding length. + * Pads `string` on the left and right sides if it is shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. * * @static * @memberOf _ @@ -9793,14 +9979,13 @@ leftLength = floor(mid), rightLength = ceil(mid); - chars = createPad('', rightLength, chars); + chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; } /** - * Pads `string` on the left side if it is shorter then the given padding - * length. The `chars` string may be truncated if the number of padding - * characters exceeds the padding length. + * Pads `string` on the left side if it is shorter than `length`. Padding + * characters are truncated if they exceed `length`. * * @static * @memberOf _ @@ -9820,15 +10005,11 @@ * _.padLeft('abc', 3); * // => 'abc' */ - function padLeft(string, length, chars) { - string = baseToString(string); - return string && (createPad(string, length, chars) + string); - } + var padLeft = createPadDir(); /** - * Pads `string` on the right side if it is shorter then the given padding - * length. The `chars` string may be truncated if the number of padding - * characters exceeds the padding length. + * Pads `string` on the right side if it is shorter than `length`. Padding + * characters are truncated if they exceed `length`. * * @static * @memberOf _ @@ -9848,18 +10029,15 @@ * _.padRight('abc', 3); * // => 'abc' */ - function padRight(string, length, chars) { - string = baseToString(string); - return string && (string + createPad(string, length, chars)); - } + var padRight = createPadDir(true); /** * Converts `string` to an integer of the specified radix. If `radix` is * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * **Note:** This method aligns with the ES5 implementation of `parseInt`. - * See the [ES5 spec](https://es5.github.io/#E) for more details. + * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E) + * of `parseInt`. * * @static * @memberOf _ @@ -9939,8 +10117,7 @@ } /** - * Converts `string` to snake case. - * See [Wikipedia](https://en.wikipedia.org/wiki/Snake_case) for more details. + * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case). * * @static * @memberOf _ @@ -9963,9 +10140,7 @@ }); /** - * Converts `string` to start case. - * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage) - * for more details. + * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). * * @static * @memberOf _ @@ -10024,9 +10199,9 @@ * properties may be accessed as free variables in the template. If a setting * object is provided it takes precedence over `_.templateSettings` values. * - * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. - * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) - * for more details. + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. * * For more information on precompiling templates see * [lodash's custom builds documentation](https://lodash.com/custom-builds). @@ -10238,7 +10413,7 @@ * // => 'abc' * * _.map([' foo ', ' bar '], _.trim); - * // => ['foo', 'bar] + * // => ['foo', 'bar'] */ function trim(string, chars, guard) { var value = string; @@ -10346,7 +10521,7 @@ * 'length': 24, * 'separator': /,? +/ * }); - * //=> 'hi-diddly-ho there...' + * // => 'hi-diddly-ho there...' * * _.trunc('hi-diddly-ho there, neighborino', { * 'omission': ' [...]' @@ -10465,7 +10640,7 @@ * @static * @memberOf _ * @category Utility - * @param {*} func The function to attempt. + * @param {Function} func The function to attempt. * @returns {*} Returns the `func` result or error object. * @example * @@ -10478,20 +10653,13 @@ * elements = []; * } */ - function attempt() { - var func = arguments[0], - length = arguments.length, - args = Array(length ? (length - 1) : 0); - - while (--length > 0) { - args[length - 1] = arguments[length]; - } + var attempt = restParam(function(func, args) { try { return func.apply(undefined, args); } catch(e) { return isError(e) ? e : new Error(e); } - } + }); /** * Creates a function that invokes `func` with the `this` binding of `thisArg` @@ -10628,12 +10796,11 @@ * * var users = [ * { 'user': 'barney' }, - * { 'user': 'fred' }, - * { 'user': 'pebbles' } + * { 'user': 'fred' } * ]; * * _.find(users, _.matchesProperty('user', 'fred')); - * // => { 'user': 'fred', 'age': 40 } + * // => { 'user': 'fred' } */ function matchesProperty(key, value) { return baseMatchesProperty(key + '', baseClone(value, true)); @@ -10644,6 +10811,9 @@ * destination object. If `object` is a function then methods are added to * its prototype as well. * + * **Note:** Use `_.runInContext` to create a pristine `lodash` function + * for mixins to avoid conflicts caused by modifying the original. + * * @static * @memberOf _ * @category Utility @@ -10661,7 +10831,7 @@ * }); * } * - * // use `_.runInContext` to avoid potential conflicts (esp. in Node.js) + * // use `_.runInContext` to avoid conflicts (esp. in Node.js) * var _ = require('lodash').runInContext(); * * _.mixin({ 'vowels': vowels }); @@ -10711,12 +10881,10 @@ return function() { var chainAll = this.__chain__; if (chain || chainAll) { - var result = object(this.__wrapped__); - (result.__actions__ = arrayCopy(this.__actions__)).push({ - 'func': func, - 'args': arguments, - 'thisArg': object - }); + var result = object(this.__wrapped__), + actions = result.__actions__ = arrayCopy(this.__actions__); + + actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); result.__chain__ = chainAll; return result; } @@ -10783,7 +10951,7 @@ * var getName = _.property('user'); * * _.map(users, getName); - * // => ['fred', barney'] + * // => ['fred', 'barney'] * * _.pluck(_.sortBy(users, getName), 'user'); * // => ['barney', 'fred'] @@ -10793,7 +10961,7 @@ } /** - * The inverse of `_.property`; this method creates a function which returns + * The opposite of `_.property`; this method creates a function which returns * the property value of a given key on `object`. * * @static @@ -10971,16 +11139,16 @@ * `-Infinity` is returned. If an iteratee function is provided it is invoked * for each value in `collection` to generate the criterion by which the value * is ranked. The `iteratee` is bound to `thisArg` and invoked with three - * arguments; (value, index, collection). + * arguments: (value, index, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -11007,11 +11175,11 @@ * _.max(users, function(chr) { * return chr.age; * }); - * // => { 'user': 'fred', 'age': 40 }; + * // => { 'user': 'fred', 'age': 40 } * * // using the `_.property` callback shorthand * _.max(users, 'age'); - * // => { 'user': 'fred', 'age': 40 }; + * // => { 'user': 'fred', 'age': 40 } */ var max = createExtremum(arrayMax); @@ -11020,16 +11188,16 @@ * `Infinity` is returned. If an iteratee function is provided it is invoked * for each value in `collection` to generate the criterion by which the value * is ranked. The `iteratee` is bound to `thisArg` and invoked with three - * arguments; (value, index, collection). + * arguments: (value, index, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -11056,11 +11224,11 @@ * _.min(users, function(chr) { * return chr.age; * }); - * // => { 'user': 'barney', 'age': 36 }; + * // => { 'user': 'barney', 'age': 36 } * * // using the `_.property` callback shorthand * _.min(users, 'age'); - * // => { 'user': 'barney', 'age': 36 }; + * // => { 'user': 'barney', 'age': 36 } */ var min = createExtremum(arrayMin, true); @@ -11071,26 +11239,45 @@ * @memberOf _ * @category Math * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the sum. * @example * - * _.sum([4, 6, 2]); - * // => 12 + * _.sum([4, 6]); + * // => 10 * - * _.sum({ 'a': 4, 'b': 6, 'c': 2 }); - * // => 12 + * _.sum({ 'a': 4, 'b': 6 }); + * // => 10 + * + * var objects = [ + * { 'n': 4 }, + * { 'n': 6 } + * ]; + * + * _.sum(objects, function(object) { + * return object.n; + * }); + * // => 10 + * + * // using the `_.property` callback shorthand + * _.sum(objects, 'n'); + * // => 10 */ - function sum(collection) { - if (!isArray(collection)) { - collection = toIterable(collection); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = null; } - var length = collection.length, - result = 0; + var func = getCallback(), + noIteratee = iteratee == null; - while (length--) { - result += +collection[length] || 0; + if (!(func === baseCallback && noIteratee)) { + noIteratee = false; + iteratee = func(iteratee, thisArg, 3); } - return result; + return noIteratee + ? arraySum(isArray(collection) ? collection : toIterable(collection)) + : baseSum(collection, iteratee); } /*------------------------------------------------------------------------*/ @@ -11189,6 +11376,7 @@ lodash.reject = reject; lodash.remove = remove; lodash.rest = rest; + lodash.restParam = restParam; lodash.shuffle = shuffle; lodash.slice = slice; lodash.sortBy = sortBy; @@ -11480,8 +11668,11 @@ // Add `LazyWrapper` methods to `lodash.prototype`. baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var lodashFunc = lodash[methodName], - checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), + var lodashFunc = lodash[methodName]; + if (!lodashFunc) { + return; + } + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName); lodash.prototype[methodName] = function() { @@ -11540,6 +11731,19 @@ }; }); + // Map minified function names to their real names. + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name, + names = realNames[key] || (realNames[key] = []); + + names.push({ 'name': methodName, 'func': lodashFunc }); + } + }); + + realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': null }]; + // Add functions to the lazy wrapper. LazyWrapper.prototype.clone = lazyClone; LazyWrapper.prototype.reverse = lazyReverse; diff --git a/internal/arrayEach.js b/internal/arrayEach.js index 652fc5361..0f5138242 100644 --- a/internal/arrayEach.js +++ b/internal/arrayEach.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.forEach` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayEachRight.js b/internal/arrayEachRight.js index 226307e00..367e066d8 100644 --- a/internal/arrayEachRight.js +++ b/internal/arrayEachRight.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.forEachRight` for arrays without support for - * callback shorthands or `this` binding. + * callback shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayEvery.js b/internal/arrayEvery.js index 1f486a36d..3fe6ed277 100644 --- a/internal/arrayEvery.js +++ b/internal/arrayEvery.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.every` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayFilter.js b/internal/arrayFilter.js index 2aa968208..e14fe0690 100644 --- a/internal/arrayFilter.js +++ b/internal/arrayFilter.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.filter` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayMap.js b/internal/arrayMap.js index 80ccb8f28..777c7c9f3 100644 --- a/internal/arrayMap.js +++ b/internal/arrayMap.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.map` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayReduce.js b/internal/arrayReduce.js index 39343185c..f948c8e52 100644 --- a/internal/arrayReduce.js +++ b/internal/arrayReduce.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.reduce` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayReduceRight.js b/internal/arrayReduceRight.js index 177940745..d4d68dff0 100644 --- a/internal/arrayReduceRight.js +++ b/internal/arrayReduceRight.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.reduceRight` for arrays without support for - * callback shorthands or `this` binding. + * callback shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arraySome.js b/internal/arraySome.js index d62a12a80..f7a0bb58e 100644 --- a/internal/arraySome.js +++ b/internal/arraySome.js @@ -1,6 +1,6 @@ /** * A specialized version of `_.some` for arrays without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arraySum.js b/internal/arraySum.js new file mode 100644 index 000000000..59ccd999c --- /dev/null +++ b/internal/arraySum.js @@ -0,0 +1,18 @@ +/** + * A specialized version of `_.sum` for arrays without support for iteratees. + * + * @private + * @param {Array} array The array to iterate over. + * @returns {number} Returns the sum. + */ +function arraySum(array) { + var length = array.length, + result = 0; + + while (length--) { + result += +array[length] || 0; + } + return result; +} + +module.exports = arraySum; diff --git a/internal/baseBindAll.js b/internal/baseBindAll.js deleted file mode 100644 index b951d7215..000000000 --- a/internal/baseBindAll.js +++ /dev/null @@ -1,26 +0,0 @@ -var createWrapper = require('./createWrapper'); - -/** Used to compose bitmasks for wrapper metadata. */ -var BIND_FLAG = 1; - -/** - * The base implementation of `_.bindAll` without support for individual - * method name arguments. - * - * @private - * @param {Object} object The object to bind and assign the bound methods to. - * @param {string[]} methodNames The object method names to bind. - * @returns {Object} Returns `object`. - */ -function baseBindAll(object, methodNames) { - var index = -1, - length = methodNames.length; - - while (++index < length) { - var key = methodNames[index]; - object[key] = createWrapper(object[key], BIND_FLAG, object); - } - return object; -} - -module.exports = baseBindAll; diff --git a/internal/baseCallback.js b/internal/baseCallback.js index 684d67dcd..ebbefd8ce 100644 --- a/internal/baseCallback.js +++ b/internal/baseCallback.js @@ -2,8 +2,7 @@ var baseMatches = require('./baseMatches'), baseMatchesProperty = require('./baseMatchesProperty'), baseProperty = require('./baseProperty'), bindCallback = require('./bindCallback'), - identity = require('../utility/identity'), - isBindable = require('./isBindable'); + identity = require('../utility/identity'); /** * The base implementation of `_.callback` which supports specifying the @@ -18,9 +17,9 @@ var baseMatches = require('./baseMatches'), function baseCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function') { - return (typeof thisArg != 'undefined' && isBindable(func)) - ? bindCallback(func, thisArg, argCount) - : func; + return typeof thisArg == 'undefined' + ? func + : bindCallback(func, thisArg, argCount); } if (func == null) { return identity; diff --git a/internal/baseClone.js b/internal/baseClone.js index 5f8587a0a..e83e202ca 100644 --- a/internal/baseClone.js +++ b/internal/baseClone.js @@ -54,9 +54,8 @@ cloneableTags[weakMapTag] = false; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; diff --git a/internal/baseDelay.js b/internal/baseDelay.js index 12fc5ffb5..c405c37b6 100644 --- a/internal/baseDelay.js +++ b/internal/baseDelay.js @@ -1,5 +1,3 @@ -var baseSlice = require('./baseSlice'); - /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -10,14 +8,14 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * @private * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. - * @param {Object} args The `arguments` object to slice and provide to `func`. + * @param {Object} args The arguments provide to `func`. * @returns {number} Returns the timer id. */ -function baseDelay(func, wait, args, fromIndex) { +function baseDelay(func, wait, args) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); + return setTimeout(function() { func.apply(undefined, args); }, wait); } module.exports = baseDelay; diff --git a/internal/baseEach.js b/internal/baseEach.js index ac4863e16..09ef5a3a4 100644 --- a/internal/baseEach.js +++ b/internal/baseEach.js @@ -1,6 +1,5 @@ var baseForOwn = require('./baseForOwn'), - isLength = require('./isLength'), - toObject = require('./toObject'); + createBaseEach = require('./createBaseEach'); /** * The base implementation of `_.forEach` without support for callback @@ -11,20 +10,6 @@ var baseForOwn = require('./baseForOwn'), * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ -function baseEach(collection, iteratee) { - var length = collection ? collection.length : 0; - if (!isLength(length)) { - return baseForOwn(collection, iteratee); - } - var index = -1, - iterable = toObject(collection); - - while (++index < length) { - if (iteratee(iterable[index], index, iterable) === false) { - break; - } - } - return collection; -} +var baseEach = createBaseEach(baseForOwn); module.exports = baseEach; diff --git a/internal/baseEachRight.js b/internal/baseEachRight.js index 65e5ba806..f0520a8b4 100644 --- a/internal/baseEachRight.js +++ b/internal/baseEachRight.js @@ -1,6 +1,5 @@ var baseForOwnRight = require('./baseForOwnRight'), - isLength = require('./isLength'), - toObject = require('./toObject'); + createBaseEach = require('./createBaseEach'); /** * The base implementation of `_.forEachRight` without support for callback @@ -11,18 +10,6 @@ var baseForOwnRight = require('./baseForOwnRight'), * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ -function baseEachRight(collection, iteratee) { - var length = collection ? collection.length : 0; - if (!isLength(length)) { - return baseForOwnRight(collection, iteratee); - } - var iterable = toObject(collection); - while (length--) { - if (iteratee(iterable[length], length, iterable) === false) { - break; - } - } - return collection; -} +var baseEachRight = createBaseEach(baseForOwnRight, true); module.exports = baseEachRight; diff --git a/internal/baseEvery.js b/internal/baseEvery.js index c6f3adbe3..a1fc1f351 100644 --- a/internal/baseEvery.js +++ b/internal/baseEvery.js @@ -2,7 +2,7 @@ var baseEach = require('./baseEach'); /** * The base implementation of `_.every` without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. diff --git a/internal/baseFilter.js b/internal/baseFilter.js index 5536fdbf9..27773a47e 100644 --- a/internal/baseFilter.js +++ b/internal/baseFilter.js @@ -2,7 +2,7 @@ var baseEach = require('./baseEach'); /** * The base implementation of `_.filter` without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. diff --git a/internal/baseFindIndex.js b/internal/baseFindIndex.js new file mode 100644 index 000000000..7d4b50248 --- /dev/null +++ b/internal/baseFindIndex.js @@ -0,0 +1,23 @@ +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for callback shorthands and `this` binding. + * + * @private + * @param {Array} array The array to search. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +module.exports = baseFindIndex; diff --git a/internal/baseFlatten.js b/internal/baseFlatten.js index 70637478b..2a5421c97 100644 --- a/internal/baseFlatten.js +++ b/internal/baseFlatten.js @@ -11,11 +11,10 @@ var isArguments = require('../lang/isArguments'), * @param {Array} array The array to flatten. * @param {boolean} isDeep Specify a deep flatten. * @param {boolean} isStrict Restrict flattening to arrays and `arguments` objects. - * @param {number} fromIndex The index to start from. * @returns {Array} Returns the new flattened array. */ -function baseFlatten(array, isDeep, isStrict, fromIndex) { - var index = fromIndex - 1, +function baseFlatten(array, isDeep, isStrict) { + var index = -1, length = array.length, resIndex = -1, result = []; @@ -26,7 +25,7 @@ function baseFlatten(array, isDeep, isStrict, fromIndex) { if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). - value = baseFlatten(value, isDeep, isStrict, 0); + value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, valLength = value.length; diff --git a/internal/baseFor.js b/internal/baseFor.js index 1141c6596..dc9b91c7d 100644 --- a/internal/baseFor.js +++ b/internal/baseFor.js @@ -1,4 +1,4 @@ -var toObject = require('./toObject'); +var createBaseFor = require('./createBaseFor'); /** * The base implementation of `baseForIn` and `baseForOwn` which iterates @@ -12,19 +12,6 @@ var toObject = require('./toObject'); * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ -function baseFor(object, iteratee, keysFunc) { - var index = -1, - iterable = toObject(object), - props = keysFunc(object), - length = props.length; - - while (++index < length) { - var key = props[index]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } - } - return object; -} +var baseFor = createBaseFor(); module.exports = baseFor; diff --git a/internal/baseForRight.js b/internal/baseForRight.js index 455dc9e84..5ddd19132 100644 --- a/internal/baseForRight.js +++ b/internal/baseForRight.js @@ -1,4 +1,4 @@ -var toObject = require('./toObject'); +var createBaseFor = require('./createBaseFor'); /** * This function is like `baseFor` except that it iterates over properties @@ -10,18 +10,6 @@ var toObject = require('./toObject'); * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ -function baseForRight(object, iteratee, keysFunc) { - var iterable = toObject(object), - props = keysFunc(object), - length = props.length; - - while (length--) { - var key = props[length]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } - } - return object; -} +var baseForRight = createBaseFor(true); module.exports = baseForRight; diff --git a/internal/baseInvoke.js b/internal/baseInvoke.js deleted file mode 100644 index 76b566cb5..000000000 --- a/internal/baseInvoke.js +++ /dev/null @@ -1,28 +0,0 @@ -var baseEach = require('./baseEach'), - isLength = require('./isLength'); - -/** - * The base implementation of `_.invoke` which requires additional arguments - * to be provided as an array of arguments rather than individually. - * - * @private - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|string} methodName The name of the method to invoke or - * the function invoked per iteration. - * @param {Array} [args] The arguments to invoke the method with. - * @returns {Array} Returns the array of results. - */ -function baseInvoke(collection, methodName, args) { - var index = -1, - isFunc = typeof methodName == 'function', - length = collection ? collection.length : 0, - result = isLength(length) ? Array(length) : []; - - baseEach(collection, function(value) { - var func = isFunc ? methodName : (value != null && value[methodName]); - result[++index] = func ? func.apply(value, args) : undefined; - }); - return result; -} - -module.exports = baseInvoke; diff --git a/internal/baseIsEqual.js b/internal/baseIsEqual.js index 8672d10e0..fc22dc4cd 100644 --- a/internal/baseIsEqual.js +++ b/internal/baseIsEqual.js @@ -8,12 +8,12 @@ var baseIsEqualDeep = require('./baseIsEqualDeep'); * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparing values. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ -function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { +function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { // Exit early for identical values. if (value === other) { // Treat `+0` vs. `-0` as not equal. @@ -28,7 +28,7 @@ function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { // Return `false` unless both values are `NaN`. return value !== value && other !== other; } - return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB); + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); } module.exports = baseIsEqual; diff --git a/internal/baseIsEqualDeep.js b/internal/baseIsEqualDeep.js index 8fb89ae17..3e18d195e 100644 --- a/internal/baseIsEqualDeep.js +++ b/internal/baseIsEqualDeep.js @@ -7,6 +7,7 @@ var equalArrays = require('./equalArrays'), /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', + funcTag = '[object Function]', objectTag = '[object Object]'; /** Used for native method references. */ @@ -16,9 +17,8 @@ var objectProto = Object.prototype; var hasOwnProperty = objectProto.hasOwnProperty; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -32,12 +32,12 @@ var objToString = objectProto.toString; * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing objects. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackB) { +function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, @@ -59,21 +59,27 @@ function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, othIsArr = isTypedArray(other); } } - var objIsObj = objTag == objectTag, - othIsObj = othTag == objectTag, + var objIsObj = (objTag == objectTag || (isLoose && objTag == funcTag)), + othIsObj = (othTag == objectTag || (isLoose && othTag == funcTag)), isSameTag = objTag == othTag; if (isSameTag && !(objIsArr || objIsObj)) { return equalByTag(object, other, objTag); } - var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), - othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + if (isLoose) { + if (!isSameTag && !(objIsObj && othIsObj)) { + return false; + } + } else { + var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - if (valWrapped || othWrapped) { - return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB); - } - if (!isSameTag) { - return false; + if (valWrapped || othWrapped) { + return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + if (!isSameTag) { + return false; + } } // Assume cyclic values are equal. // For more information on detecting circular references see https://es5.github.io/#JO. @@ -90,7 +96,7 @@ function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackA.push(object); stackB.push(other); - var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isWhere, stackA, stackB); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); stackA.pop(); stackB.pop(); diff --git a/internal/baseIsMatch.js b/internal/baseIsMatch.js index 8409e1fba..54a1ccbae 100644 --- a/internal/baseIsMatch.js +++ b/internal/baseIsMatch.js @@ -1,14 +1,8 @@ var baseIsEqual = require('./baseIsEqual'); -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - /** * The base implementation of `_.isMatch` without support for callback - * shorthands or `this` binding. + * shorthands and `this` binding. * * @private * @param {Object} object The object to inspect. @@ -19,30 +13,27 @@ var hasOwnProperty = objectProto.hasOwnProperty; * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, props, values, strictCompareFlags, customizer) { - var length = props.length; - if (object == null) { - return !length; - } var index = -1, + length = props.length, noCustomizer = !customizer; while (++index < length) { if ((noCustomizer && strictCompareFlags[index]) ? values[index] !== object[props[index]] - : !hasOwnProperty.call(object, props[index]) + : !(props[index] in object) ) { return false; } } index = -1; while (++index < length) { - var key = props[index]; - if (noCustomizer && strictCompareFlags[index]) { - var result = hasOwnProperty.call(object, key); - } else { - var objValue = object[key], - srcValue = values[index]; + var key = props[index], + objValue = object[key], + srcValue = values[index]; + if (noCustomizer && strictCompareFlags[index]) { + var result = typeof objValue != 'undefined' || (key in object); + } else { result = customizer ? customizer(objValue, srcValue, key) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(srcValue, objValue, customizer, true); diff --git a/internal/baseMap.js b/internal/baseMap.js index b1b26c815..232b2565e 100644 --- a/internal/baseMap.js +++ b/internal/baseMap.js @@ -2,7 +2,7 @@ var baseEach = require('./baseEach'); /** * The base implementation of `_.map` without support for callback shorthands - * or `this` binding. + * and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. diff --git a/internal/baseMatches.js b/internal/baseMatches.js index cc9b62f58..7f07c7dd3 100644 --- a/internal/baseMatches.js +++ b/internal/baseMatches.js @@ -1,12 +1,8 @@ var baseIsMatch = require('./baseIsMatch'), + constant = require('../utility/constant'), isStrictComparable = require('./isStrictComparable'), - keys = require('../object/keys'); - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; + keys = require('../object/keys'), + toObject = require('./toObject'); /** * The base implementation of `_.matches` which does not clone `source`. @@ -19,13 +15,17 @@ function baseMatches(source) { var props = keys(source), length = props.length; + if (!length) { + return constant(true); + } if (length == 1) { var key = props[0], value = source[key]; if (isStrictComparable(value)) { return function(object) { - return object != null && object[key] === value && hasOwnProperty.call(object, key); + return object != null && object[key] === value && + (typeof value != 'undefined' || (key in toObject(object))); }; } } @@ -38,7 +38,7 @@ function baseMatches(source) { strictCompareFlags[length] = isStrictComparable(value); } return function(object) { - return baseIsMatch(object, props, values, strictCompareFlags); + return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags); }; } diff --git a/internal/baseMatchesProperty.js b/internal/baseMatchesProperty.js index 49e31e6ee..60b672f1d 100644 --- a/internal/baseMatchesProperty.js +++ b/internal/baseMatchesProperty.js @@ -1,5 +1,6 @@ var baseIsEqual = require('./baseIsEqual'), - isStrictComparable = require('./isStrictComparable'); + isStrictComparable = require('./isStrictComparable'), + toObject = require('./toObject'); /** * The base implementation of `_.matchesProperty` which does not coerce `key` @@ -13,7 +14,8 @@ var baseIsEqual = require('./baseIsEqual'), function baseMatchesProperty(key, value) { if (isStrictComparable(value)) { return function(object) { - return object != null && object[key] === value; + return object != null && object[key] === value && + (typeof value != 'undefined' || (key in toObject(object))); }; } return function(object) { diff --git a/internal/baseMergeDeep.js b/internal/baseMergeDeep.js index 825e1ea37..f40c4fe56 100644 --- a/internal/baseMergeDeep.js +++ b/internal/baseMergeDeep.js @@ -40,7 +40,7 @@ function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stack if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) { result = isArray(value) ? value - : (value ? arrayCopy(value) : []); + : ((value && value.length) ? arrayCopy(value) : []); } else if (isPlainObject(srcValue) || isArguments(srcValue)) { result = isArguments(value) diff --git a/internal/basePullAt.js b/internal/basePullAt.js deleted file mode 100644 index bfde76cdf..000000000 --- a/internal/basePullAt.js +++ /dev/null @@ -1,35 +0,0 @@ -var baseAt = require('./baseAt'), - baseCompareAscending = require('./baseCompareAscending'), - isIndex = require('./isIndex'); - -/** Used for native method references. */ -var arrayProto = Array.prototype; - -/** Native method references. */ -var splice = arrayProto.splice; - -/** - * The base implementation of `_.pullAt` without support for individual - * index arguments. - * - * @private - * @param {Array} array The array to modify. - * @param {number[]} indexes The indexes of elements to remove. - * @returns {Array} Returns the new array of removed elements. - */ -function basePullAt(array, indexes) { - var length = indexes.length, - result = baseAt(array, indexes); - - indexes.sort(baseCompareAscending); - while (length--) { - var index = parseFloat(indexes[length]); - if (index != previous && isIndex(index)) { - var previous = index; - splice.call(array, index, 1); - } - } - return result; -} - -module.exports = basePullAt; diff --git a/internal/baseReduce.js b/internal/baseReduce.js index 73229277e..5e6ae555f 100644 --- a/internal/baseReduce.js +++ b/internal/baseReduce.js @@ -1,6 +1,6 @@ /** * The base implementation of `_.reduce` and `_.reduceRight` without support - * for callback shorthands or `this` binding, which iterates over `collection` + * for callback shorthands and `this` binding, which iterates over `collection` * using the provided `eachFunc`. * * @private diff --git a/internal/baseSome.js b/internal/baseSome.js index 7b261b6a8..39a005880 100644 --- a/internal/baseSome.js +++ b/internal/baseSome.js @@ -2,7 +2,7 @@ var baseEach = require('./baseEach'); /** * The base implementation of `_.some` without support for callback shorthands - * or `this` binding. + * and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. diff --git a/internal/baseSum.js b/internal/baseSum.js new file mode 100644 index 000000000..019e5ae6e --- /dev/null +++ b/internal/baseSum.js @@ -0,0 +1,20 @@ +var baseEach = require('./baseEach'); + +/** + * The base implementation of `_.sum` without support for callback shorthands + * and `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ +function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; +} + +module.exports = baseSum; diff --git a/internal/baseWhile.js b/internal/baseWhile.js new file mode 100644 index 000000000..c24e9bd9d --- /dev/null +++ b/internal/baseWhile.js @@ -0,0 +1,24 @@ +var baseSlice = require('./baseSlice'); + +/** + * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`, + * and `_.takeWhile` without support for callback shorthands and `this` binding. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ +function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); +} + +module.exports = baseWhile; diff --git a/internal/baseWrapperValue.js b/internal/baseWrapperValue.js index f400ca7b2..49c14fb2e 100644 --- a/internal/baseWrapperValue.js +++ b/internal/baseWrapperValue.js @@ -14,7 +14,7 @@ var push = arrayProto.push; * @private * @param {*} value The unwrapped value. * @param {Array} actions Actions to peform to resolve the unwrapped value. - * @returns {*} Returns the resolved unwrapped value. + * @returns {*} Returns the resolved value. */ function baseWrapperValue(value, actions) { var result = value; diff --git a/internal/binaryIndex.js b/internal/binaryIndex.js index fb4900038..cd5a072d3 100644 --- a/internal/binaryIndex.js +++ b/internal/binaryIndex.js @@ -12,8 +12,7 @@ var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @param {boolean} [retHighest] Specify returning the highest, instead - * of the lowest, index at which a value should be inserted into `array`. + * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ diff --git a/internal/binaryIndexBy.js b/internal/binaryIndexBy.js index 338e8192b..bac9472d7 100644 --- a/internal/binaryIndexBy.js +++ b/internal/binaryIndexBy.js @@ -17,8 +17,7 @@ var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function} iteratee The function invoked per iteration. - * @param {boolean} [retHighest] Specify returning the highest, instead - * of the lowest, index at which a value should be inserted into `array`. + * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ diff --git a/internal/createAggregator.js b/internal/createAggregator.js index d277cc997..5137861a0 100644 --- a/internal/createAggregator.js +++ b/internal/createAggregator.js @@ -7,6 +7,9 @@ var baseCallback = require('./baseCallback'), * object composed from the results of running each element in the collection * through an iteratee. * + * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, + * and `_.partition`. + * * @private * @param {Function} setter The function to set keys and values of the accumulator object. * @param {Function} [initializer] The function to initialize the accumulator object. diff --git a/internal/createAssigner.js b/internal/createAssigner.js index 9a40cba73..79b02ebd8 100644 --- a/internal/createAssigner.js +++ b/internal/createAssigner.js @@ -5,6 +5,8 @@ var bindCallback = require('./bindCallback'), * Creates a function that assigns properties of source object(s) to a given * destination object. * + * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. + * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. diff --git a/internal/createBaseEach.js b/internal/createBaseEach.js new file mode 100644 index 000000000..5f9f2bf84 --- /dev/null +++ b/internal/createBaseEach.js @@ -0,0 +1,30 @@ +var isLength = require('./isLength'), + toObject = require('./toObject'); + +/** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, + iterable = toObject(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; +} + +module.exports = createBaseEach; diff --git a/internal/createBaseFor.js b/internal/createBaseFor.js new file mode 100644 index 000000000..3c2cac510 --- /dev/null +++ b/internal/createBaseFor.js @@ -0,0 +1,27 @@ +var toObject = require('./toObject'); + +/** + * Creates a base function for `_.forIn` or `_.forInRight`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), + props = keysFunc(object), + length = props.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length)) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} + +module.exports = createBaseFor; diff --git a/internal/createComposer.js b/internal/createComposer.js deleted file mode 100644 index cb817593d..000000000 --- a/internal/createComposer.js +++ /dev/null @@ -1,39 +0,0 @@ -/** Used as the `TypeError` message for "Functions" methods. */ -var FUNC_ERROR_TEXT = 'Expected a function'; - -/** - * Creates a function to compose other functions into a single function. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new composer function. - */ -function createComposer(fromRight) { - return function() { - var length = arguments.length, - index = length, - fromIndex = fromRight ? (length - 1) : 0; - - if (!length) { - return function() { return arguments[0]; }; - } - var funcs = Array(length); - while (index--) { - funcs[index] = arguments[index]; - if (typeof funcs[index] != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - } - return function() { - var index = fromIndex, - result = funcs[index].apply(this, arguments); - - while ((fromRight ? index-- : ++index < length)) { - result = funcs[index].call(this, result); - } - return result; - }; - }; -} - -module.exports = createComposer; diff --git a/internal/createCurry.js b/internal/createCurry.js new file mode 100644 index 000000000..e140e711f --- /dev/null +++ b/internal/createCurry.js @@ -0,0 +1,23 @@ +var createWrapper = require('./createWrapper'), + isIterateeCall = require('./isIterateeCall'); + +/** + * Creates a `_.curry` or `_.curryRight` function. + * + * @private + * @param {boolean} flag The curry bit flag. + * @returns {Function} Returns the new curry function. + */ +function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = null; + } + var result = createWrapper(func, flag, null, null, null, null, null, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; +} + +module.exports = createCurry; diff --git a/internal/createExtremum.js b/internal/createExtremum.js index c21fce8fd..4d05d2e89 100644 --- a/internal/createExtremum.js +++ b/internal/createExtremum.js @@ -7,7 +7,7 @@ var baseCallback = require('./baseCallback'), toIterable = require('./toIterable'); /** - * Creates a function that gets the extremum value of a collection. + * Creates a `_.max` or `_.min` function. * * @private * @param {Function} arrayFunc The function to get the extremum value from an array. diff --git a/internal/createFind.js b/internal/createFind.js new file mode 100644 index 000000000..f65cfbf70 --- /dev/null +++ b/internal/createFind.js @@ -0,0 +1,25 @@ +var baseCallback = require('./baseCallback'), + baseFind = require('./baseFind'), + baseFindIndex = require('./baseFindIndex'), + isArray = require('../lang/isArray'); + +/** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new find function. + */ +function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = baseCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + } +} + +module.exports = createFind; diff --git a/internal/createFindIndex.js b/internal/createFindIndex.js new file mode 100644 index 000000000..3947bea9a --- /dev/null +++ b/internal/createFindIndex.js @@ -0,0 +1,21 @@ +var baseCallback = require('./baseCallback'), + baseFindIndex = require('./baseFindIndex'); + +/** + * Creates a `_.findIndex` or `_.findLastIndex` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new find function. + */ +function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = baseCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; +} + +module.exports = createFindIndex; diff --git a/internal/createFindKey.js b/internal/createFindKey.js new file mode 100644 index 000000000..0ce85e4cb --- /dev/null +++ b/internal/createFindKey.js @@ -0,0 +1,18 @@ +var baseCallback = require('./baseCallback'), + baseFind = require('./baseFind'); + +/** + * Creates a `_.findKey` or `_.findLastKey` function. + * + * @private + * @param {Function} objectFunc The function to iterate over an object. + * @returns {Function} Returns the new find function. + */ +function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = baseCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; +} + +module.exports = createFindKey; diff --git a/internal/createFlow.js b/internal/createFlow.js new file mode 100644 index 000000000..825c13f48 --- /dev/null +++ b/internal/createFlow.js @@ -0,0 +1,64 @@ +var LodashWrapper = require('./LodashWrapper'), + getData = require('./getData'), + getFuncName = require('./getFuncName'), + isArray = require('../lang/isArray'), + isLaziable = require('./isLaziable'); + +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ +function createFlow(fromRight) { + return function() { + var length = arguments.length; + if (!length) { + return function() { return arguments[0]; }; + } + var wrapper, + index = fromRight ? length : -1, + leftIndex = 0, + funcs = Array(length); + + while ((fromRight ? index-- : ++index < length)) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var funcName = wrapper ? '' : getFuncName(func); + wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper; + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + funcName = getFuncName(func); + + var data = funcName == 'wrapper' ? getData(func) : null; + if (data && isLaziable(data[0])) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments; + if (wrapper && args.length == 1 && isArray(args[0])) { + return wrapper.plant(args[0]).value(); + } + var index = 0, + result = funcs[index].apply(this, args); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; +} + +module.exports = createFlow; diff --git a/internal/createForEach.js b/internal/createForEach.js new file mode 100644 index 000000000..b0d1659b3 --- /dev/null +++ b/internal/createForEach.js @@ -0,0 +1,20 @@ +var bindCallback = require('./bindCallback'), + isArray = require('../lang/isArray'); + +/** + * Creates a function for `_.forEach` or `_.forEachRight`. + * + * @private + * @param {Function} arrayFunc The function to iterate over an array. + * @param {Function} eachFunc The function to iterate over a collection. + * @returns {Function} Returns the new each function. + */ +function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayFunc(collection, iteratee) + : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; +} + +module.exports = createForEach; diff --git a/internal/createForIn.js b/internal/createForIn.js new file mode 100644 index 000000000..7d7933b5a --- /dev/null +++ b/internal/createForIn.js @@ -0,0 +1,20 @@ +var bindCallback = require('./bindCallback'), + keysIn = require('../object/keysIn'); + +/** + * Creates a function for `_.forIn` or `_.forInRight`. + * + * @private + * @param {Function} objectFunc The function to iterate over an object. + * @returns {Function} Returns the new each function. + */ +function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; +} + +module.exports = createForIn; diff --git a/internal/createForOwn.js b/internal/createForOwn.js new file mode 100644 index 000000000..6690972e4 --- /dev/null +++ b/internal/createForOwn.js @@ -0,0 +1,19 @@ +var bindCallback = require('./bindCallback'); + +/** + * Creates a function for `_.forOwn` or `_.forOwnRight`. + * + * @private + * @param {Function} objectFunc The function to iterate over an object. + * @returns {Function} Returns the new each function. + */ +function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; +} + +module.exports = createForOwn; diff --git a/internal/createHybridWrapper.js b/internal/createHybridWrapper.js index edd25c7d8..fb62371bf 100644 --- a/internal/createHybridWrapper.js +++ b/internal/createHybridWrapper.js @@ -2,8 +2,10 @@ var arrayCopy = require('./arrayCopy'), composeArgs = require('./composeArgs'), composeArgsRight = require('./composeArgsRight'), createCtorWrapper = require('./createCtorWrapper'), + isLaziable = require('./isLaziable'), reorder = require('./reorder'), - replaceHolders = require('./replaceHolders'); + replaceHolders = require('./replaceHolders'), + setData = require('./setData'); /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -13,7 +15,7 @@ var BIND_FLAG = 1, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, - ARY_FLAG = 256; + ARY_FLAG = 128; /* Native method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; @@ -81,7 +83,12 @@ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partials if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } - var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity); + var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity], + result = createHybridWrapper.apply(undefined, newData); + + if (isLaziable(func)) { + setData(result, newData); + } result.placeholder = placeholder; return result; } diff --git a/internal/createPadDir.js b/internal/createPadDir.js new file mode 100644 index 000000000..430a5a130 --- /dev/null +++ b/internal/createPadDir.js @@ -0,0 +1,18 @@ +var baseToString = require('./baseToString'), + createPadding = require('./createPadding'); + +/** + * Creates a function for `_.padLeft` or `_.padRight`. + * + * @private + * @param {boolean} [fromRight] Specify padding from the right. + * @returns {Function} Returns the new pad function. + */ +function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return string && ((fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string)); + }; +} + +module.exports = createPadDir; diff --git a/internal/createPad.js b/internal/createPadding.js similarity index 74% rename from internal/createPad.js rename to internal/createPadding.js index 1c700c9bd..57979926f 100644 --- a/internal/createPad.js +++ b/internal/createPadding.js @@ -7,9 +7,8 @@ var ceil = Math.ceil; var nativeIsFinite = global.isFinite; /** - * Creates the pad required for `string` based on the given padding length. - * The `chars` string may be truncated if the number of padding characters - * exceeds the padding length. + * Creates the padding required for `string` based on the given `length`. + * The `chars` string is truncated if the number of characters exceeds `length`. * * @private * @param {string} string The string to create padding for. @@ -17,7 +16,7 @@ var nativeIsFinite = global.isFinite; * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the pad for `string`. */ -function createPad(string, length, chars) { +function createPadding(string, length, chars) { var strLength = string.length; length = +length; @@ -29,4 +28,4 @@ function createPad(string, length, chars) { return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); } -module.exports = createPad; +module.exports = createPadding; diff --git a/internal/createPartial.js b/internal/createPartial.js new file mode 100644 index 000000000..c0e42b615 --- /dev/null +++ b/internal/createPartial.js @@ -0,0 +1,20 @@ +var createWrapper = require('./createWrapper'), + replaceHolders = require('./replaceHolders'), + restParam = require('../function/restParam'); + +/** + * Creates a `_.partial` or `_.partialRight` function. + * + * @private + * @param {boolean} flag The partial bit flag. + * @returns {Function} Returns the new partial function. + */ +function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, null, partials, holders); + }); + return partialFunc; +} + +module.exports = createPartial; diff --git a/internal/createReduce.js b/internal/createReduce.js new file mode 100644 index 000000000..3633a6f71 --- /dev/null +++ b/internal/createReduce.js @@ -0,0 +1,22 @@ +var baseCallback = require('./baseCallback'), + baseReduce = require('./baseReduce'), + isArray = require('../lang/isArray'); + +/** + * Creates a function for `_.reduce` or `_.reduceRight`. + * + * @private + * @param {Function} arrayFunc The function to iterate over an array. + * @param {Function} eachFunc The function to iterate over a collection. + * @returns {Function} Returns the new each function. + */ +function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayFunc(collection, iteratee, accumulator, initFromArray) + : baseReduce(collection, baseCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; +} + +module.exports = createReduce; diff --git a/internal/createSortedIndex.js b/internal/createSortedIndex.js new file mode 100644 index 000000000..86c78520c --- /dev/null +++ b/internal/createSortedIndex.js @@ -0,0 +1,20 @@ +var baseCallback = require('./baseCallback'), + binaryIndex = require('./binaryIndex'), + binaryIndexBy = require('./binaryIndexBy'); + +/** + * Creates a `_.sortedIndex` or `_.sortedLastIndex` function. + * + * @private + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {Function} Returns the new index function. + */ +function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + return iteratee == null + ? binaryIndex(array, value, retHighest) + : binaryIndexBy(array, value, baseCallback(iteratee, thisArg, 1), retHighest); + }; +} + +module.exports = createSortedIndex; diff --git a/internal/createWrapper.js b/internal/createWrapper.js index f0dc3fd79..6b5379917 100644 --- a/internal/createWrapper.js +++ b/internal/createWrapper.js @@ -60,10 +60,10 @@ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, a partials = holders = null; } - var data = !isBindKey && getData(func), + var data = isBindKey ? null : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; - if (data && data !== true) { + if (data) { mergeData(newData, data); bitmask = newData[1]; arity = newData[9]; diff --git a/internal/equalArrays.js b/internal/equalArrays.js index e1838e018..c3bae1b23 100644 --- a/internal/equalArrays.js +++ b/internal/equalArrays.js @@ -7,18 +7,18 @@ * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing arrays. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ -function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stackB) { +function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { var index = -1, arrLength = array.length, othLength = other.length, result = true; - if (arrLength != othLength && !(isWhere && othLength > arrLength)) { + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { return false; } // Deep compare the contents, ignoring non-numeric properties. @@ -28,23 +28,23 @@ function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stack result = undefined; if (customizer) { - result = isWhere + result = isLoose ? customizer(othValue, arrValue, index) : customizer(arrValue, othValue, index); } if (typeof result == 'undefined') { // Recursively compare arrays (susceptible to call stack limits). - if (isWhere) { + if (isLoose) { var othIndex = othLength; while (othIndex--) { othValue = other[othIndex]; - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); if (result) { break; } } } else { - result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); } } } diff --git a/internal/equalObjects.js b/internal/equalObjects.js index a9c6656a8..6c4110a6f 100644 --- a/internal/equalObjects.js +++ b/internal/equalObjects.js @@ -15,26 +15,26 @@ var hasOwnProperty = objectProto.hasOwnProperty; * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing values. - * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, stackB) { +function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; - if (objLength != othLength && !isWhere) { + if (objLength != othLength && !isLoose) { return false; } - var hasCtor, + var skipCtor = isLoose, index = -1; while (++index < objLength) { var key = objProps[index], - result = hasOwnProperty.call(other, key); + result = isLoose ? key in other : hasOwnProperty.call(other, key); if (result) { var objValue = object[key], @@ -42,21 +42,21 @@ function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, sta result = undefined; if (customizer) { - result = isWhere + result = isLoose ? customizer(othValue, objValue, key) : customizer(objValue, othValue, key); } if (typeof result == 'undefined') { // Recursively compare objects (susceptible to call stack limits). - result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB); + result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB); } } if (!result) { return false; } - hasCtor || (hasCtor = key == 'constructor'); + skipCtor || (skipCtor = key == 'constructor'); } - if (!hasCtor) { + if (!skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; diff --git a/internal/extremumBy.js b/internal/extremumBy.js index 9fed607e6..ddbfe0ca4 100644 --- a/internal/extremumBy.js +++ b/internal/extremumBy.js @@ -7,7 +7,7 @@ var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, /** * Gets the extremum value of `collection` invoking `iteratee` for each value * in `collection` to generate the criterion by which the value is ranked. - * The `iteratee` is invoked with three arguments; (value, index, collection). + * The `iteratee` is invoked with three arguments: (value, index, collection). * * @private * @param {Array|Object|string} collection The collection to iterate over. diff --git a/internal/getFuncName.js b/internal/getFuncName.js new file mode 100644 index 000000000..3102b7142 --- /dev/null +++ b/internal/getFuncName.js @@ -0,0 +1,37 @@ +var baseProperty = require('./baseProperty'), + constant = require('../utility/constant'), + realNames = require('./realNames'), + support = require('../support'); + +/** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ +var getFuncName = (function() { + if (!support.funcNames) { + return constant(''); + } + if (constant.name == 'constant') { + return baseProperty('name'); + } + return function(func) { + var result = func.name, + array = realNames[result], + length = array ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + }; +}()); + +module.exports = getFuncName; diff --git a/internal/indexOfNaN.js b/internal/indexOfNaN.js index 798b6a459..05b8207d7 100644 --- a/internal/indexOfNaN.js +++ b/internal/indexOfNaN.js @@ -1,6 +1,5 @@ /** * Gets the index at which the first occurrence of `NaN` is found in `array`. - * If `fromRight` is provided elements of `array` are iterated from right to left. * * @private * @param {Array} array The array to search. diff --git a/internal/isBindable.js b/internal/isBindable.js deleted file mode 100644 index 6f1be761a..000000000 --- a/internal/isBindable.js +++ /dev/null @@ -1,38 +0,0 @@ -var baseSetData = require('./baseSetData'), - isNative = require('../lang/isNative'), - support = require('../support'); - -/** Used to detect named functions. */ -var reFuncName = /^\s*function[ \n\r\t]+\w/; - -/** Used to detect functions containing a `this` reference. */ -var reThis = /\bthis\b/; - -/** Used to resolve the decompiled source of functions. */ -var fnToString = Function.prototype.toString; - -/** - * Checks if `func` is eligible for `this` binding. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is eligible, else `false`. - */ -function isBindable(func) { - var result = !(support.funcNames ? func.name : support.funcDecomp); - - if (!result) { - var source = fnToString.call(func); - if (!support.funcNames) { - result = !reFuncName.test(source); - } - if (!result) { - // Check if `func` references the `this` keyword and store the result. - result = reThis.test(source) || isNative(func); - baseSetData(func, result); - } - } - return result; -} - -module.exports = isBindable; diff --git a/internal/isIndex.js b/internal/isIndex.js index 89bd88dcd..caa2b94b1 100644 --- a/internal/isIndex.js +++ b/internal/isIndex.js @@ -1,7 +1,6 @@ /** - * Used as the maximum length of an array-like value. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) - * for more details. + * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * of an array-like value. */ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; diff --git a/internal/isLaziable.js b/internal/isLaziable.js new file mode 100644 index 000000000..7b4829924 --- /dev/null +++ b/internal/isLaziable.js @@ -0,0 +1,17 @@ +var LazyWrapper = require('./LazyWrapper'), + getFuncName = require('./getFuncName'), + lodash = require('../chain/lodash'); + +/** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`. + */ +function isLaziable(func) { + var funcName = getFuncName(func); + return !!funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype; +} + +module.exports = isLaziable; diff --git a/internal/isLength.js b/internal/isLength.js index 8e1bf44e9..1e3f11c10 100644 --- a/internal/isLength.js +++ b/internal/isLength.js @@ -1,16 +1,13 @@ /** - * Used as the maximum length of an array-like value. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) - * for more details. + * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * of an array-like value. */ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is based on ES `ToLength`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. + * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). * * @private * @param {*} value The value to check. diff --git a/internal/isObjectLike.js b/internal/isObjectLike.js index ba6566995..8ca0585b7 100644 --- a/internal/isObjectLike.js +++ b/internal/isObjectLike.js @@ -6,7 +6,7 @@ * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ function isObjectLike(value) { - return (value && typeof value == 'object') || false; + return !!value && typeof value == 'object'; } module.exports = isObjectLike; diff --git a/internal/mergeData.js b/internal/mergeData.js index 1cfeaaf94..29297c78a 100644 --- a/internal/mergeData.js +++ b/internal/mergeData.js @@ -5,11 +5,10 @@ var arrayCopy = require('./arrayCopy'), /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, - BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, - CURRY_RIGHT_FLAG = 16, - REARG_FLAG = 128, - ARY_FLAG = 256; + CURRY_FLAG = 8, + ARY_FLAG = 128, + REARG_FLAG = 256; /** Used as the internal argument placeholder. */ var PLACEHOLDER = '__lodash_placeholder__'; @@ -35,22 +34,13 @@ var nativeMin = Math.min; function mergeData(data, source) { var bitmask = data[1], srcBitmask = source[1], - newBitmask = bitmask | srcBitmask; + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < ARY_FLAG; - var arityFlags = ARY_FLAG | REARG_FLAG, - bindFlags = BIND_FLAG | BIND_KEY_FLAG, - comboFlags = arityFlags | bindFlags | CURRY_BOUND_FLAG | CURRY_RIGHT_FLAG; - - var isAry = bitmask & ARY_FLAG && !(srcBitmask & ARY_FLAG), - isRearg = bitmask & REARG_FLAG && !(srcBitmask & REARG_FLAG), - argPos = (isRearg ? data : source)[7], - ary = (isAry ? data : source)[8]; - - var isCommon = !(bitmask >= REARG_FLAG && srcBitmask > bindFlags) && - !(bitmask > bindFlags && srcBitmask >= REARG_FLAG); - - var isCombo = (newBitmask >= arityFlags && newBitmask <= comboFlags) && - (bitmask < REARG_FLAG || ((isRearg || isAry) && argPos.length <= ary)); + var isCombo = + (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) || + (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) || + (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { diff --git a/internal/realNames.js b/internal/realNames.js new file mode 100644 index 000000000..aa0d52926 --- /dev/null +++ b/internal/realNames.js @@ -0,0 +1,4 @@ +/** Used to lookup unminified function names. */ +var realNames = {}; + +module.exports = realNames; diff --git a/internal/shimIsPlainObject.js b/internal/shimIsPlainObject.js index a2150e26c..3e75ce49a 100644 --- a/internal/shimIsPlainObject.js +++ b/internal/shimIsPlainObject.js @@ -11,9 +11,8 @@ var objectProto = Object.prototype; var hasOwnProperty = objectProto.hasOwnProperty; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; diff --git a/lang/clone.js b/lang/clone.js index eca0a2f14..76f030ac9 100644 --- a/lang/clone.js +++ b/lang/clone.js @@ -9,12 +9,12 @@ var baseClone = require('../internal/baseClone'), * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value [, index|key, object]). * - * **Note:** This method is loosely based on the structured clone algorithm. + * **Note:** This method is loosely based on the + * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, - * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) - * for more details. + * Maps, Sets, and WeakMaps. * * @static * @memberOf _ diff --git a/lang/cloneDeep.js b/lang/cloneDeep.js index b6e3c44ad..4319d453c 100644 --- a/lang/cloneDeep.js +++ b/lang/cloneDeep.js @@ -7,12 +7,12 @@ var baseClone = require('../internal/baseClone'), * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value [, index|key, object]). * - * **Note:** This method is loosely based on the structured clone algorithm. + * **Note:** This method is loosely based on the + * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, - * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) - * for more details. + * Maps, Sets, and WeakMaps. * * @static * @memberOf _ diff --git a/lang/isArguments.js b/lang/isArguments.js index 653c91819..07c266c26 100644 --- a/lang/isArguments.js +++ b/lang/isArguments.js @@ -8,9 +8,8 @@ var argsTag = '[object Arguments]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -32,7 +31,7 @@ var objToString = objectProto.toString; */ function isArguments(value) { var length = isObjectLike(value) ? value.length : undefined; - return (isLength(length) && objToString.call(value) == argsTag) || false; + return isLength(length) && objToString.call(value) == argsTag; } module.exports = isArguments; diff --git a/lang/isArray.js b/lang/isArray.js index e67daa713..36a560875 100644 --- a/lang/isArray.js +++ b/lang/isArray.js @@ -9,9 +9,8 @@ var arrayTag = '[object Array]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -35,7 +34,7 @@ var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray; * // => false */ var isArray = nativeIsArray || function(value) { - return (isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag) || false; + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; }; module.exports = isArray; diff --git a/lang/isBoolean.js b/lang/isBoolean.js index 821e0dac6..8999da34c 100644 --- a/lang/isBoolean.js +++ b/lang/isBoolean.js @@ -7,9 +7,8 @@ var boolTag = '[object Boolean]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -30,7 +29,7 @@ var objToString = objectProto.toString; * // => false */ function isBoolean(value) { - return (value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag) || false; + return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag); } module.exports = isBoolean; diff --git a/lang/isDate.js b/lang/isDate.js index 2ea8d4d50..5d80e3dc4 100644 --- a/lang/isDate.js +++ b/lang/isDate.js @@ -7,9 +7,8 @@ var dateTag = '[object Date]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -30,7 +29,7 @@ var objToString = objectProto.toString; * // => false */ function isDate(value) { - return (isObjectLike(value) && objToString.call(value) == dateTag) || false; + return isObjectLike(value) && objToString.call(value) == dateTag; } module.exports = isDate; diff --git a/lang/isElement.js b/lang/isElement.js index a517ff5ac..4a1e31225 100644 --- a/lang/isElement.js +++ b/lang/isElement.js @@ -6,9 +6,8 @@ var isObjectLike = require('../internal/isObjectLike'), var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -29,13 +28,13 @@ var objToString = objectProto.toString; * // => false */ function isElement(value) { - return (value && value.nodeType === 1 && isObjectLike(value) && - (objToString.call(value).indexOf('Element') > -1)) || false; + return !!value && value.nodeType === 1 && isObjectLike(value) && + (objToString.call(value).indexOf('Element') > -1); } // Fallback for environments without DOM support. if (!support.dom) { isElement = function(value) { - return (value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value)) || false; + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); }; } diff --git a/lang/isEqual.js b/lang/isEqual.js index 3be9b0b68..691eecc6b 100644 --- a/lang/isEqual.js +++ b/lang/isEqual.js @@ -7,7 +7,7 @@ var baseIsEqual = require('../internal/baseIsEqual'), * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three - * arguments; (value, other [, index|key]). + * arguments: (value, other [, index|key]). * * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Objects are compared by diff --git a/lang/isError.js b/lang/isError.js index 22af4a483..4ec836db4 100644 --- a/lang/isError.js +++ b/lang/isError.js @@ -7,9 +7,8 @@ var errorTag = '[object Error]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -31,7 +30,7 @@ var objToString = objectProto.toString; * // => false */ function isError(value) { - return (isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag) || false; + return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag; } module.exports = isError; diff --git a/lang/isFinite.js b/lang/isFinite.js index eaf1781fc..fc250ca1a 100644 --- a/lang/isFinite.js +++ b/lang/isFinite.js @@ -7,9 +7,7 @@ var nativeIsFinite = global.isFinite, /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on ES `Number.isFinite`. See the - * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) - * for more details. + * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite). * * @static * @memberOf _ diff --git a/lang/isFunction.js b/lang/isFunction.js index 7a4190a08..44c54155b 100644 --- a/lang/isFunction.js +++ b/lang/isFunction.js @@ -8,9 +8,8 @@ var funcTag = '[object Function]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; diff --git a/lang/isMatch.js b/lang/isMatch.js index bc3eefae0..bd6576b03 100644 --- a/lang/isMatch.js +++ b/lang/isMatch.js @@ -1,20 +1,15 @@ var baseIsMatch = require('../internal/baseIsMatch'), bindCallback = require('../internal/bindCallback'), isStrictComparable = require('../internal/isStrictComparable'), - keys = require('../object/keys'); - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; + keys = require('../object/keys'), + toObject = require('../internal/toObject'); /** * Performs a deep comparison between `object` and `source` to determine if * `object` contains equivalent property values. If `customizer` is provided * it is invoked to compare values. If `customizer` returns `undefined` * comparisons are handled by the method instead. The `customizer` is bound - * to `thisArg` and invoked with three arguments; (value, other, index|key). + * to `thisArg` and invoked with three arguments: (value, other, index|key). * * **Note:** This method supports comparing properties of arrays, booleans, * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions @@ -52,13 +47,19 @@ function isMatch(object, source, customizer, thisArg) { var props = keys(source), length = props.length; + if (!length) { + return true; + } + if (object == null) { + return false; + } customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); if (!customizer && length == 1) { var key = props[0], value = source[key]; if (isStrictComparable(value)) { - return object != null && value === object[key] && hasOwnProperty.call(object, key); + return value === object[key] && (typeof value != 'undefined' || (key in toObject(object))); } } var values = Array(length), @@ -68,7 +69,7 @@ function isMatch(object, source, customizer, thisArg) { value = values[length] = source[props[length]]; strictCompareFlags[length] = isStrictComparable(value); } - return baseIsMatch(object, props, values, strictCompareFlags, customizer); + return baseIsMatch(toObject(object), props, values, strictCompareFlags, customizer); } module.exports = isMatch; diff --git a/lang/isNaN.js b/lang/isNaN.js index 30142df57..cf83d5663 100644 --- a/lang/isNaN.js +++ b/lang/isNaN.js @@ -3,9 +3,8 @@ var isNumber = require('./isNumber'); /** * Checks if `value` is `NaN`. * - * **Note:** This method is not the same as native `isNaN` which returns `true` - * for `undefined` and other non-numeric values. See the [ES5 spec](https://es5.github.io/#x15.1.2.4) - * for more details. + * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4) + * which returns `true` for `undefined` and other non-numeric values. * * @static * @memberOf _ diff --git a/lang/isNative.js b/lang/isNative.js index 6fa3b3e33..25229e2ba 100644 --- a/lang/isNative.js +++ b/lang/isNative.js @@ -14,9 +14,8 @@ var objectProto = Object.prototype; var fnToString = Function.prototype.toString; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -49,7 +48,7 @@ function isNative(value) { if (objToString.call(value) == funcTag) { return reNative.test(fnToString.call(value)); } - return (isObjectLike(value) && reHostCtor.test(value)) || false; + return isObjectLike(value) && reHostCtor.test(value); } module.exports = isNative; diff --git a/lang/isNumber.js b/lang/isNumber.js index 740dbc26f..9404dc851 100644 --- a/lang/isNumber.js +++ b/lang/isNumber.js @@ -7,9 +7,8 @@ var numberTag = '[object Number]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -36,7 +35,7 @@ var objToString = objectProto.toString; * // => false */ function isNumber(value) { - return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag) || false; + return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag); } module.exports = isNumber; diff --git a/lang/isObject.js b/lang/isObject.js index 00fdc18e0..63c3e95be 100644 --- a/lang/isObject.js +++ b/lang/isObject.js @@ -1,9 +1,7 @@ /** - * Checks if `value` is the language type of `Object`. + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * **Note:** See the [ES5 spec](https://es5.github.io/#x8) for more details. - * * @static * @memberOf _ * @category Lang @@ -24,7 +22,7 @@ function isObject(value) { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; - return type == 'function' || (value && type == 'object') || false; + return type == 'function' || (!!value && type == 'object'); } module.exports = isObject; diff --git a/lang/isPlainObject.js b/lang/isPlainObject.js index 8c7f31ffb..89e0c74eb 100644 --- a/lang/isPlainObject.js +++ b/lang/isPlainObject.js @@ -8,9 +8,8 @@ var objectTag = '[object Object]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; diff --git a/lang/isRegExp.js b/lang/isRegExp.js index 0b44096ea..296b60a2b 100644 --- a/lang/isRegExp.js +++ b/lang/isRegExp.js @@ -7,9 +7,8 @@ var regexpTag = '[object RegExp]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; diff --git a/lang/isString.js b/lang/isString.js index bb71d4a9c..f4155dcb0 100644 --- a/lang/isString.js +++ b/lang/isString.js @@ -7,9 +7,8 @@ var stringTag = '[object String]'; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -30,7 +29,7 @@ var objToString = objectProto.toString; * // => false */ function isString(value) { - return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag) || false; + return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag); } module.exports = isString; diff --git a/lang/isTypedArray.js b/lang/isTypedArray.js index 7f656813b..4642c7a40 100644 --- a/lang/isTypedArray.js +++ b/lang/isTypedArray.js @@ -46,9 +46,8 @@ typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; var objectProto = Object.prototype; /** - * Used to resolve the `toStringTag` of values. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) - * for more details. + * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * of values. */ var objToString = objectProto.toString; @@ -69,7 +68,7 @@ var objToString = objectProto.toString; * // => false */ function isTypedArray(value) { - return (isObjectLike(value) && isLength(value.length) && typedArrayTags[objToString.call(value)]) || false; + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; } module.exports = isTypedArray; diff --git a/math/max.js b/math/max.js index 0c13b1e62..68088410d 100644 --- a/math/max.js +++ b/math/max.js @@ -6,16 +6,16 @@ var arrayMax = require('../internal/arrayMax'), * `-Infinity` is returned. If an iteratee function is provided it is invoked * for each value in `collection` to generate the criterion by which the value * is ranked. The `iteratee` is bound to `thisArg` and invoked with three - * arguments; (value, index, collection). + * arguments: (value, index, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -42,11 +42,11 @@ var arrayMax = require('../internal/arrayMax'), * _.max(users, function(chr) { * return chr.age; * }); - * // => { 'user': 'fred', 'age': 40 }; + * // => { 'user': 'fred', 'age': 40 } * * // using the `_.property` callback shorthand * _.max(users, 'age'); - * // => { 'user': 'fred', 'age': 40 }; + * // => { 'user': 'fred', 'age': 40 } */ var max = createExtremum(arrayMax); diff --git a/math/min.js b/math/min.js index cb3e8c880..4381b0a3d 100644 --- a/math/min.js +++ b/math/min.js @@ -6,16 +6,16 @@ var arrayMin = require('../internal/arrayMin'), * `Infinity` is returned. If an iteratee function is provided it is invoked * for each value in `collection` to generate the criterion by which the value * is ranked. The `iteratee` is bound to `thisArg` and invoked with three - * arguments; (value, index, collection). + * arguments: (value, index, collection). * - * If a property name is provided for `predicate` the created `_.property` + * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * - * If an object is provided for `predicate` the created `_.matches` style + * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * @@ -42,11 +42,11 @@ var arrayMin = require('../internal/arrayMin'), * _.min(users, function(chr) { * return chr.age; * }); - * // => { 'user': 'barney', 'age': 36 }; + * // => { 'user': 'barney', 'age': 36 } * * // using the `_.property` callback shorthand * _.min(users, 'age'); - * // => { 'user': 'barney', 'age': 36 }; + * // => { 'user': 'barney', 'age': 36 } */ var min = createExtremum(arrayMin, true); diff --git a/math/sum.js b/math/sum.js index 5efe9ce0f..0e1878054 100644 --- a/math/sum.js +++ b/math/sum.js @@ -1,4 +1,8 @@ -var isArray = require('../lang/isArray'), +var arraySum = require('../internal/arraySum'), + baseCallback = require('../internal/baseCallback'), + baseSum = require('../internal/baseSum'), + isArray = require('../lang/isArray'), + isIterateeCall = require('../internal/isIterateeCall'), toIterable = require('../internal/toIterable'); /** @@ -8,26 +12,41 @@ var isArray = require('../lang/isArray'), * @memberOf _ * @category Math * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the sum. * @example * - * _.sum([4, 6, 2]); - * // => 12 + * _.sum([4, 6]); + * // => 10 * - * _.sum({ 'a': 4, 'b': 6, 'c': 2 }); - * // => 12 + * _.sum({ 'a': 4, 'b': 6 }); + * // => 10 + * + * var objects = [ + * { 'n': 4 }, + * { 'n': 6 } + * ]; + * + * _.sum(objects, function(object) { + * return object.n; + * }); + * // => 10 + * + * // using the `_.property` callback shorthand + * _.sum(objects, 'n'); + * // => 10 */ -function sum(collection) { - if (!isArray(collection)) { - collection = toIterable(collection); +function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = null; } - var length = collection.length, - result = 0; + var noIteratee = iteratee == null; - while (length--) { - result += +collection[length] || 0; - } - return result; + iteratee = noIteratee ? iteratee : baseCallback(iteratee, thisArg, 3); + return noIteratee + ? arraySum(isArray(collection) ? collection : toIterable(collection)) + : baseSum(collection, iteratee); } module.exports = sum; diff --git a/object/assign.js b/object/assign.js index 77201f99a..0914c4517 100644 --- a/object/assign.js +++ b/object/assign.js @@ -5,7 +5,7 @@ var baseAssign = require('../internal/baseAssign'), * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. * If `customizer` is provided it is invoked to produce the assigned values. - * The `customizer` is bound to `thisArg` and invoked with five arguments; + * The `customizer` is bound to `thisArg` and invoked with five arguments: * (objectValue, sourceValue, key, object, source). * * @static diff --git a/object/defaults.js b/object/defaults.js index f4da858f2..b4efe02a9 100644 --- a/object/defaults.js +++ b/object/defaults.js @@ -1,6 +1,6 @@ -var arrayCopy = require('../internal/arrayCopy'), - assign = require('./assign'), - assignDefaults = require('../internal/assignDefaults'); +var assign = require('./assign'), + assignDefaults = require('../internal/assignDefaults'), + restParam = require('../function/restParam'); /** * Assigns own enumerable properties of source object(s) to the destination @@ -18,13 +18,13 @@ var arrayCopy = require('../internal/arrayCopy'), * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ -function defaults(object) { +var defaults = restParam(function(args) { + var object = args[0]; if (object == null) { return object; } - var args = arrayCopy(arguments); args.push(assignDefaults); return assign.apply(undefined, args); -} +}); module.exports = defaults; diff --git a/object/findKey.js b/object/findKey.js index 6ef567ed5..1359df340 100644 --- a/object/findKey.js +++ b/object/findKey.js @@ -1,10 +1,9 @@ -var baseCallback = require('../internal/baseCallback'), - baseFind = require('../internal/baseFind'), - baseForOwn = require('../internal/baseForOwn'); +var baseForOwn = require('../internal/baseForOwn'), + createFindKey = require('../internal/createFindKey'); /** - * This method is like `_.findIndex` except that it returns the key of the - * first element `predicate` returns truthy for, instead of the element itself. + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. @@ -50,9 +49,6 @@ var baseCallback = require('../internal/baseCallback'), * _.findKey(users, 'active'); * // => 'barney' */ -function findKey(object, predicate, thisArg) { - predicate = baseCallback(predicate, thisArg, 3); - return baseFind(object, predicate, baseForOwn, true); -} +var findKey = createFindKey(baseForOwn); module.exports = findKey; diff --git a/object/findLastKey.js b/object/findLastKey.js index e867fc505..42893a4b7 100644 --- a/object/findLastKey.js +++ b/object/findLastKey.js @@ -1,6 +1,5 @@ -var baseCallback = require('../internal/baseCallback'), - baseFind = require('../internal/baseFind'), - baseForOwnRight = require('../internal/baseForOwnRight'); +var baseForOwnRight = require('../internal/baseForOwnRight'), + createFindKey = require('../internal/createFindKey'); /** * This method is like `_.findKey` except that it iterates over elements of @@ -50,9 +49,6 @@ var baseCallback = require('../internal/baseCallback'), * _.findLastKey(users, 'active'); * // => 'pebbles' */ -function findLastKey(object, predicate, thisArg) { - predicate = baseCallback(predicate, thisArg, 3); - return baseFind(object, predicate, baseForOwnRight, true); -} +var findLastKey = createFindKey(baseForOwnRight); module.exports = findLastKey; diff --git a/object/forIn.js b/object/forIn.js index 3beacefed..afb58f291 100644 --- a/object/forIn.js +++ b/object/forIn.js @@ -1,11 +1,10 @@ var baseFor = require('../internal/baseFor'), - bindCallback = require('../internal/bindCallback'), - keysIn = require('./keysIn'); + createForIn = require('../internal/createForIn'); /** * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked - * with three arguments; (value, key, object). Iterator functions may exit + * with three arguments: (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * * @static @@ -29,11 +28,6 @@ var baseFor = require('../internal/baseFor'), * }); * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed) */ -function forIn(object, iteratee, thisArg) { - if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { - iteratee = bindCallback(iteratee, thisArg, 3); - } - return baseFor(object, iteratee, keysIn); -} +var forIn = createForIn(baseFor); module.exports = forIn; diff --git a/object/forInRight.js b/object/forInRight.js index bc19e090b..6780b9297 100644 --- a/object/forInRight.js +++ b/object/forInRight.js @@ -1,6 +1,5 @@ var baseForRight = require('../internal/baseForRight'), - bindCallback = require('../internal/bindCallback'), - keysIn = require('./keysIn'); + createForIn = require('../internal/createForIn'); /** * This method is like `_.forIn` except that it iterates over properties of @@ -27,9 +26,6 @@ var baseForRight = require('../internal/baseForRight'), * }); * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c' */ -function forInRight(object, iteratee, thisArg) { - iteratee = bindCallback(iteratee, thisArg, 3); - return baseForRight(object, iteratee, keysIn); -} +var forInRight = createForIn(baseForRight); module.exports = forInRight; diff --git a/object/forOwn.js b/object/forOwn.js index a4dcf026e..3d5cfcac5 100644 --- a/object/forOwn.js +++ b/object/forOwn.js @@ -1,10 +1,10 @@ var baseForOwn = require('../internal/baseForOwn'), - bindCallback = require('../internal/bindCallback'); + createForOwn = require('../internal/createForOwn'); /** * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with - * three arguments; (value, key, object). Iterator functions may exit iteration + * three arguments: (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * * @static @@ -28,11 +28,6 @@ var baseForOwn = require('../internal/baseForOwn'), * }); * // => logs 'a' and 'b' (iteration order is not guaranteed) */ -function forOwn(object, iteratee, thisArg) { - if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { - iteratee = bindCallback(iteratee, thisArg, 3); - } - return baseForOwn(object, iteratee); -} +var forOwn = createForOwn(baseForOwn); module.exports = forOwn; diff --git a/object/forOwnRight.js b/object/forOwnRight.js index d48f88e48..8122338b3 100644 --- a/object/forOwnRight.js +++ b/object/forOwnRight.js @@ -1,6 +1,5 @@ -var baseForRight = require('../internal/baseForRight'), - bindCallback = require('../internal/bindCallback'), - keys = require('./keys'); +var baseForOwnRight = require('../internal/baseForOwnRight'), + createForOwn = require('../internal/createForOwn'); /** * This method is like `_.forOwn` except that it iterates over properties of @@ -27,9 +26,6 @@ var baseForRight = require('../internal/baseForRight'), * }); * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b' */ -function forOwnRight(object, iteratee, thisArg) { - iteratee = bindCallback(iteratee, thisArg, 3); - return baseForRight(object, iteratee, keys); -} +var forOwnRight = createForOwn(baseForOwnRight); module.exports = forOwnRight; diff --git a/object/mapValues.js b/object/mapValues.js index edde5da5e..32edea040 100644 --- a/object/mapValues.js +++ b/object/mapValues.js @@ -4,7 +4,7 @@ var baseCallback = require('../internal/baseCallback'), /** * Creates an object with the same keys as `object` and values generated by * running each own enumerable property of `object` through `iteratee`. The - * iteratee function is bound to `thisArg` and invoked with three arguments; + * iteratee function is bound to `thisArg` and invoked with three arguments: * (value, key, object). * * If a property name is provided for `iteratee` the created `_.property` diff --git a/object/merge.js b/object/merge.js index eade105b0..5f8d3a0a6 100644 --- a/object/merge.js +++ b/object/merge.js @@ -8,7 +8,7 @@ var baseMerge = require('../internal/baseMerge'), * provided it is invoked to produce the merged values of the destination and * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked - * with five arguments; (objectValue, sourceValue, key, object, source). + * with five arguments: (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ diff --git a/object/omit.js b/object/omit.js index c504d852d..2154b4a5e 100644 --- a/object/omit.js +++ b/object/omit.js @@ -4,7 +4,8 @@ var arrayMap = require('../internal/arrayMap'), bindCallback = require('../internal/bindCallback'), keysIn = require('./keysIn'), pickByArray = require('../internal/pickByArray'), - pickByCallback = require('../internal/pickByCallback'); + pickByCallback = require('../internal/pickByCallback'), + restParam = require('../function/restParam'); /** * The opposite of `_.pick`; this method creates an object composed of the @@ -12,7 +13,7 @@ var arrayMap = require('../internal/arrayMap'), * Property names may be specified as individual arguments or as arrays of * property names. If `predicate` is provided it is invoked for each property * of `object` omitting the properties `predicate` returns truthy for. The - * predicate is bound to `thisArg` and invoked with three arguments; + * predicate is bound to `thisArg` and invoked with three arguments: * (value, key, object). * * @static @@ -34,18 +35,18 @@ var arrayMap = require('../internal/arrayMap'), * _.omit(object, _.isNumber); * // => { 'user': 'fred' } */ -function omit(object, predicate, thisArg) { +var omit = restParam(function(object, props) { if (object == null) { return {}; } - if (typeof predicate != 'function') { - var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + if (typeof props[0] != 'function') { + var props = arrayMap(baseFlatten(props), String); return pickByArray(object, baseDifference(keysIn(object), props)); } - predicate = bindCallback(predicate, thisArg, 3); + var predicate = bindCallback(props[0], props[1], 3); return pickByCallback(object, function(value, key, object) { return !predicate(value, key, object); }); -} +}); module.exports = omit; diff --git a/object/pick.js b/object/pick.js index 93b30b88d..c880c319b 100644 --- a/object/pick.js +++ b/object/pick.js @@ -1,14 +1,15 @@ var baseFlatten = require('../internal/baseFlatten'), bindCallback = require('../internal/bindCallback'), pickByArray = require('../internal/pickByArray'), - pickByCallback = require('../internal/pickByCallback'); + pickByCallback = require('../internal/pickByCallback'), + restParam = require('../function/restParam'); /** * Creates an object composed of the picked `object` properties. Property * names may be specified as individual arguments or as arrays of property * names. If `predicate` is provided it is invoked for each property of `object` * picking the properties `predicate` returns truthy for. The predicate is - * bound to `thisArg` and invoked with three arguments; (value, key, object). + * bound to `thisArg` and invoked with three arguments: (value, key, object). * * @static * @memberOf _ @@ -29,13 +30,13 @@ var baseFlatten = require('../internal/baseFlatten'), * _.pick(object, _.isString); * // => { 'user': 'fred' } */ -function pick(object, predicate, thisArg) { +var pick = restParam(function(object, props) { if (object == null) { return {}; } - return typeof predicate == 'function' - ? pickByCallback(object, bindCallback(predicate, thisArg, 3)) - : pickByArray(object, baseFlatten(arguments, false, false, 1)); -} + return typeof props[0] == 'function' + ? pickByCallback(object, bindCallback(props[0], props[1], 3)) + : pickByArray(object, baseFlatten(props)); +}); module.exports = pick; diff --git a/object/transform.js b/object/transform.js index 8b7007327..7686c9a80 100644 --- a/object/transform.js +++ b/object/transform.js @@ -12,7 +12,7 @@ var arrayEach = require('../internal/arrayEach'), * `accumulator` object which is the result of running each of its own enumerable * properties through `iteratee`, with each invocation potentially mutating * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked - * with four arguments; (accumulator, value, key, object). Iterator functions + * with four arguments: (accumulator, value, key, object). Iterator functions * may exit iteration early by explicitly returning `false`. * * @static diff --git a/package.json b/package.json index 6f6b8403a..a4d47e984 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lodash", - "version": "3.5.0", + "version": "3.6.0", "description": "The modern build of lodash modular utilities.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", diff --git a/string/camelCase.js b/string/camelCase.js index 7f9979bc4..2d438f4aa 100644 --- a/string/camelCase.js +++ b/string/camelCase.js @@ -1,8 +1,7 @@ var createCompounder = require('../internal/createCompounder'); /** - * Converts `string` to camel case. - * See [Wikipedia](https://en.wikipedia.org/wiki/CamelCase) for more details. + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). * * @static * @memberOf _ diff --git a/string/deburr.js b/string/deburr.js index e543cc4a8..30abcffd5 100644 --- a/string/deburr.js +++ b/string/deburr.js @@ -1,13 +1,17 @@ var baseToString = require('../internal/baseToString'), deburrLetter = require('../internal/deburrLetter'); +/** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + */ +var reComboMarks = /[\u0300-\u036f\ufe20-\ufe23]/g; + /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; /** - * Deburrs `string` by converting latin-1 supplementary letters to basic latin letters. - * See [Wikipedia](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * for more details. + * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). * * @static * @memberOf _ @@ -21,7 +25,7 @@ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; */ function deburr(string) { string = baseToString(string); - return string && string.replace(reLatin1, deburrLetter); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMarks, ''); } module.exports = deburr; diff --git a/string/escape.js b/string/escape.js index 058b81374..057a2061c 100644 --- a/string/escape.js +++ b/string/escape.js @@ -23,9 +23,8 @@ var reUnescapedHtml = /[&<>"'`]/g, * [#108](https://html5sec.org/#108), and [#133](https://html5sec.org/#133) of * the [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. * - * When working with HTML you should always quote attribute values to reduce - * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) - * for more details. + * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping) + * to reduce XSS vectors. * * @static * @memberOf _ diff --git a/string/escapeRegExp.js b/string/escapeRegExp.js index f5a3fbb27..0234d67f5 100644 --- a/string/escapeRegExp.js +++ b/string/escapeRegExp.js @@ -1,16 +1,16 @@ var baseToString = require('../internal/baseToString'); /** - * Used to match `RegExp` special characters. - * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) - * for more details. + * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). + * In addition to special characters the forward slash is escaped to allow for + * easier `eval` use and `Function` compilation. */ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** - * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", - * "+", "(", ")", "[", "]", "{" and "}" in `string`. + * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?", + * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ @@ -20,7 +20,7 @@ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, * @example * * _.escapeRegExp('[lodash](https://lodash.com/)'); - * // => '\[lodash\]\(https://lodash\.com/\)' + * // => '\[lodash\]\(https:\/\/lodash\.com\/\)' */ function escapeRegExp(string) { string = baseToString(string); diff --git a/string/kebabCase.js b/string/kebabCase.js index a65f65ade..d29c2f908 100644 --- a/string/kebabCase.js +++ b/string/kebabCase.js @@ -1,9 +1,7 @@ var createCompounder = require('../internal/createCompounder'); /** - * Converts `string` to kebab case. - * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles) for - * more details. + * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). * * @static * @memberOf _ diff --git a/string/pad.js b/string/pad.js index 7d23317a6..df37ded03 100644 --- a/string/pad.js +++ b/string/pad.js @@ -1,5 +1,5 @@ var baseToString = require('../internal/baseToString'), - createPad = require('../internal/createPad'); + createPadding = require('../internal/createPadding'); /** Native method references. */ var ceil = Math.ceil, @@ -9,9 +9,8 @@ var ceil = Math.ceil, var nativeIsFinite = global.isFinite; /** - * Pads `string` on the left and right sides if it is shorter then the given - * padding length. The `chars` string may be truncated if the number of padding - * characters can't be evenly divided by the padding length. + * Pads `string` on the left and right sides if it is shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. * * @static * @memberOf _ @@ -43,7 +42,7 @@ function pad(string, length, chars) { leftLength = floor(mid), rightLength = ceil(mid); - chars = createPad('', rightLength, chars); + chars = createPadding('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; } diff --git a/string/padLeft.js b/string/padLeft.js index d9d321f77..af5a498b2 100644 --- a/string/padLeft.js +++ b/string/padLeft.js @@ -1,10 +1,8 @@ -var baseToString = require('../internal/baseToString'), - createPad = require('../internal/createPad'); +var createPadDir = require('../internal/createPadDir'); /** - * Pads `string` on the left side if it is shorter then the given padding - * length. The `chars` string may be truncated if the number of padding - * characters exceeds the padding length. + * Pads `string` on the left side if it is shorter than `length`. Padding + * characters are truncated if they exceed `length`. * * @static * @memberOf _ @@ -24,9 +22,6 @@ var baseToString = require('../internal/baseToString'), * _.padLeft('abc', 3); * // => 'abc' */ -function padLeft(string, length, chars) { - string = baseToString(string); - return string && (createPad(string, length, chars) + string); -} +var padLeft = createPadDir(); module.exports = padLeft; diff --git a/string/padRight.js b/string/padRight.js index 937ebad18..e78daa5a1 100644 --- a/string/padRight.js +++ b/string/padRight.js @@ -1,10 +1,8 @@ -var baseToString = require('../internal/baseToString'), - createPad = require('../internal/createPad'); +var createPadDir = require('../internal/createPadDir'); /** - * Pads `string` on the right side if it is shorter then the given padding - * length. The `chars` string may be truncated if the number of padding - * characters exceeds the padding length. + * Pads `string` on the right side if it is shorter than `length`. Padding + * characters are truncated if they exceed `length`. * * @static * @memberOf _ @@ -24,9 +22,6 @@ var baseToString = require('../internal/baseToString'), * _.padRight('abc', 3); * // => 'abc' */ -function padRight(string, length, chars) { - string = baseToString(string); - return string && (string + createPad(string, length, chars)); -} +var padRight = createPadDir(true); module.exports = padRight; diff --git a/string/parseInt.js b/string/parseInt.js index 06e41c26c..519dcdbba 100644 --- a/string/parseInt.js +++ b/string/parseInt.js @@ -24,8 +24,8 @@ var nativeParseInt = global.parseInt; * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * **Note:** This method aligns with the ES5 implementation of `parseInt`. - * See the [ES5 spec](https://es5.github.io/#E) for more details. + * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E) + * of `parseInt`. * * @static * @memberOf _ diff --git a/string/snakeCase.js b/string/snakeCase.js index f83a299cc..c9ebffd91 100644 --- a/string/snakeCase.js +++ b/string/snakeCase.js @@ -1,8 +1,7 @@ var createCompounder = require('../internal/createCompounder'); /** - * Converts `string` to snake case. - * See [Wikipedia](https://en.wikipedia.org/wiki/Snake_case) for more details. + * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case). * * @static * @memberOf _ diff --git a/string/startCase.js b/string/startCase.js index 8bdfa44e4..740d48a51 100644 --- a/string/startCase.js +++ b/string/startCase.js @@ -1,9 +1,7 @@ var createCompounder = require('../internal/createCompounder'); /** - * Converts `string` to start case. - * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage) - * for more details. + * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). * * @static * @memberOf _ diff --git a/string/template.js b/string/template.js index 38dba4a05..5ef49a707 100644 --- a/string/template.js +++ b/string/template.js @@ -16,9 +16,7 @@ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** - * Used to match ES template delimiters. - * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) - * for more details. + * Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; @@ -35,9 +33,9 @@ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; * properties may be accessed as free variables in the template. If a setting * object is provided it takes precedence over `_.templateSettings` values. * - * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. - * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) - * for more details. + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. * * For more information on precompiling templates see * [lodash's custom builds documentation](https://lodash.com/custom-builds). diff --git a/string/trim.js b/string/trim.js index 6feaf66cf..22cd38a5b 100644 --- a/string/trim.js +++ b/string/trim.js @@ -24,7 +24,7 @@ var baseToString = require('../internal/baseToString'), * // => 'abc' * * _.map([' foo ', ' bar '], _.trim); - * // => ['foo', 'bar] + * // => ['foo', 'bar'] */ function trim(string, chars, guard) { var value = string; diff --git a/string/trunc.js b/string/trunc.js index ac8549b00..b8e6117f2 100644 --- a/string/trunc.js +++ b/string/trunc.js @@ -43,7 +43,7 @@ var reFlags = /\w*$/; * 'length': 24, * 'separator': /,? +/ * }); - * //=> 'hi-diddly-ho there...' + * // => 'hi-diddly-ho there...' * * _.trunc('hi-diddly-ho there, neighborino', { * 'omission': ' [...]' diff --git a/support.js b/support.js index d50acaf5a..c70322f0d 100644 --- a/support.js +++ b/support.js @@ -1,8 +1,3 @@ -var isNative = require('./lang/isNative'); - -/** Used to detect functions containing a `this` reference. */ -var reThis = /\bthis\b/; - /** Used for native method references. */ var objectProto = Object.prototype; @@ -31,7 +26,7 @@ var support = {}; * @memberOf _.support * @type boolean */ - support.funcDecomp = !isNative(global.WinRTError) && reThis.test(function() { return this; }); + support.funcDecomp = /\bthis\b/.test(function() { return this; }); /** * Detect if `Function#name` is supported (all but IE). diff --git a/utility/attempt.js b/utility/attempt.js index 82b1f1794..80afe6924 100644 --- a/utility/attempt.js +++ b/utility/attempt.js @@ -1,4 +1,5 @@ -var isError = require('../lang/isError'); +var isError = require('../lang/isError'), + restParam = require('../function/restParam'); /** * Attempts to invoke `func`, returning either the result or the caught error @@ -7,7 +8,7 @@ var isError = require('../lang/isError'); * @static * @memberOf _ * @category Utility - * @param {*} func The function to attempt. + * @param {Function} func The function to attempt. * @returns {*} Returns the `func` result or error object. * @example * @@ -20,19 +21,12 @@ var isError = require('../lang/isError'); * elements = []; * } */ -function attempt() { - var func = arguments[0], - length = arguments.length, - args = Array(length ? (length - 1) : 0); - - while (--length > 0) { - args[length - 1] = arguments[length]; - } +var attempt = restParam(function(func, args) { try { return func.apply(undefined, args); } catch(e) { return isError(e) ? e : new Error(e); } -} +}); module.exports = attempt; diff --git a/utility/matchesProperty.js b/utility/matchesProperty.js index 6e5675593..89e5e0e9c 100644 --- a/utility/matchesProperty.js +++ b/utility/matchesProperty.js @@ -19,12 +19,11 @@ var baseClone = require('../internal/baseClone'), * * var users = [ * { 'user': 'barney' }, - * { 'user': 'fred' }, - * { 'user': 'pebbles' } + * { 'user': 'fred' } * ]; * * _.find(users, _.matchesProperty('user', 'fred')); - * // => { 'user': 'fred', 'age': 40 } + * // => { 'user': 'fred' } */ function matchesProperty(key, value) { return baseMatchesProperty(key + '', baseClone(value, true)); diff --git a/utility/mixin.js b/utility/mixin.js index 8fb09585f..f1a6e5261 100644 --- a/utility/mixin.js +++ b/utility/mixin.js @@ -15,6 +15,9 @@ var push = arrayProto.push; * destination object. If `object` is a function then methods are added to * its prototype as well. * + * **Note:** Use `_.runInContext` to create a pristine `lodash` function + * for mixins to avoid conflicts caused by modifying the original. + * * @static * @memberOf _ * @category Utility @@ -32,7 +35,7 @@ var push = arrayProto.push; * }); * } * - * // use `_.runInContext` to avoid potential conflicts (esp. in Node.js) + * // use `_.runInContext` to avoid conflicts (esp. in Node.js) * var _ = require('lodash').runInContext(); * * _.mixin({ 'vowels': vowels }); @@ -69,12 +72,10 @@ function mixin(object, source, options) { return function() { var chainAll = this.__chain__; if (chain || chainAll) { - var result = object(this.__wrapped__); - (result.__actions__ = arrayCopy(this.__actions__)).push({ - 'func': func, - 'args': arguments, - 'thisArg': object - }); + var result = object(this.__wrapped__), + actions = result.__actions__ = arrayCopy(this.__actions__); + + actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); result.__chain__ = chainAll; return result; } diff --git a/utility/property.js b/utility/property.js index 4f874486c..154ca0947 100644 --- a/utility/property.js +++ b/utility/property.js @@ -18,7 +18,7 @@ var baseProperty = require('../internal/baseProperty'); * var getName = _.property('user'); * * _.map(users, getName); - * // => ['fred', barney'] + * // => ['fred', 'barney'] * * _.pluck(_.sortBy(users, getName), 'user'); * // => ['barney', 'fred'] diff --git a/utility/propertyOf.js b/utility/propertyOf.js index 62bb825c6..fcd7304ce 100644 --- a/utility/propertyOf.js +++ b/utility/propertyOf.js @@ -1,5 +1,5 @@ /** - * The inverse of `_.property`; this method creates a function which returns + * The opposite of `_.property`; this method creates a function which returns * the property value of a given key on `object`. * * @static