From 54e7baecc3d20927971b4c14d2f761f166ec692c Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 17 Sep 2015 17:52:09 -0700 Subject: [PATCH] Bump to v4.0.0. --- LICENSE | 4 +- README.md | 8 +- add.js | 26 + function/after.js => after.js | 15 +- array.default.js | 77 ++ array.js | 149 ++-- array/dropRightWhile.js | 59 -- array/dropWhile.js | 59 -- array/findIndex.js | 53 -- array/findLastIndex.js | 53 -- array/flatten.js | 32 - array/head.js | 2 - array/intersection.js | 58 -- array/object.js | 2 - array/pull.js | 52 -- array/pullAt.js | 40 - array/sortedIndex.js | 53 -- array/tail.js | 2 - array/takeRightWhile.js | 59 -- array/takeWhile.js | 59 -- array/uniq.js | 71 -- array/unique.js | 2 - array/unzipWith.js | 41 - array/xor.js | 35 - array/zipObject.js | 43 - array/zipWith.js | 36 - function/ary.js => ary.js | 16 +- assign.js | 39 + assignIn.js | 38 + assignInWith.js | 36 + assignWith.js | 35 + at.js | 29 + utility/attempt.js => attempt.js | 13 +- function/before.js => before.js | 13 +- function/bind.js => bind.js | 13 +- bindAll.js | 39 + function/bindKey.js => bindKey.js | 13 +- string/camelCase.js => camelCase.js | 5 +- string/capitalize.js => capitalize.js | 11 +- math/ceil.js => ceil.js | 6 +- chain.js | 65 +- chain/chain.js | 35 - chain/commit.js | 2 - chain/concat.js | 2 - chain/lodash.js | 125 --- chain/plant.js | 2 - chain/reverse.js | 2 - chain/run.js | 2 - chain/toJSON.js | 2 - chain/toString.js | 2 - chain/value.js | 2 - chain/valueOf.js | 2 - chain/wrapperConcat.js | 34 - chain/wrapperToString.js | 17 - array/chunk.js => chunk.js | 24 +- clamp.js | 38 + clone.js | 31 + cloneDeep.js | 23 + cloneDeepWith.js | 33 + cloneWith.js | 36 + collection.default.js | 35 + collection.js | 114 +-- collection/all.js | 2 - collection/any.js | 2 - collection/at.js | 29 - collection/collect.js | 2 - collection/contains.js | 2 - collection/countBy.js | 54 -- collection/detect.js | 2 - collection/each.js | 2 - collection/eachRight.js | 2 - collection/every.js | 66 -- collection/filter.js | 61 -- collection/find.js | 56 -- collection/findLast.js | 25 - collection/findWhere.js | 37 - collection/foldl.js | 2 - collection/foldr.js | 2 - collection/forEach.js | 37 - collection/forEachRight.js | 26 - collection/groupBy.js | 59 -- collection/include.js | 2 - collection/includes.js | 57 -- collection/indexBy.js | 53 -- collection/inject.js | 2 - collection/map.js | 68 -- collection/max.js | 2 - collection/min.js | 2 - collection/partition.js | 66 -- collection/pluck.js | 31 - collection/reduce.js | 44 - collection/reduceRight.js | 29 - collection/reject.js | 50 -- collection/sample.js | 50 -- collection/select.js | 2 - collection/size.js | 30 - collection/some.js | 67 -- collection/sortBy.js | 71 -- collection/sortByAll.js | 52 -- collection/sortByOrder.js | 55 -- collection/sum.js | 2 - collection/where.js | 37 - chain/wrapperCommit.js => commit.js | 4 +- array/compact.js => compact.js | 0 concat.js | 32 + cond.js | 58 ++ conforms.js | 28 + utility/constant.js => constant.js | 2 +- countBy.js | 33 + object/create.js => create.js | 16 +- curry.js | 53 ++ function/curryRight.js => curryRight.js | 16 +- date.default.js | 5 + date.js | 7 +- date/now.js | 24 - function/debounce.js => debounce.js | 64 +- string/deburr.js => deburr.js | 18 +- defaults.js | 30 + object/defaultsDeep.js => defaultsDeep.js | 12 +- function/defer.js => defer.js | 8 +- function/delay.js => delay.js | 11 +- array/difference.js => difference.js | 19 +- differenceBy.js | 39 + differenceWith.js | 36 + array/drop.js => drop.js | 12 +- array/dropRight.js => dropRight.js | 12 +- dropRightWhile.js | 44 + dropWhile.js | 44 + each.js | 1 + eachRight.js | 1 + string/endsWith.js => endsWith.js | 13 +- eq.js | 35 + string/escape.js => escape.js | 17 +- escapeRegExp.js | 28 + every.js | 49 + array/fill.js => fill.js | 8 +- filter.js | 44 + find.js | 50 ++ findIndex.js | 43 + findKey.js | 42 + findLast.js | 33 + findLastIndex.js | 43 + findLastKey.js | 42 + flatMap.js | 30 + flatten.js | 21 + array/flattenDeep.js => flattenDeep.js | 4 +- flip.js | 27 + math/floor.js => floor.js | 6 +- function/flow.js => flow.js | 6 +- function/flowRight.js => flowRight.js | 7 +- forEach.js | 40 + forEachRight.js | 30 + object/forIn.js => forIn.js | 18 +- object/forInRight.js => forInRight.js | 12 +- object/forOwn.js => forOwn.js | 17 +- object/forOwnRight.js => forOwnRight.js | 11 +- fromPairs.js | 29 + function.default.js | 31 + function.js | 79 +- function/backflow.js | 2 - function/bindAll.js | 50 -- function/compose.js | 2 - function/curry.js | 51 -- function/modArgs.js | 58 -- functions.js | 29 + functionsIn.js | 29 + object/get.js => get.js | 7 +- groupBy.js | 38 + lang/gt.js => gt.js | 0 lang/gte.js => gte.js | 0 has.js | 34 + hasIn.js | 33 + array/first.js => head.js | 10 +- utility/identity.js => identity.js | 2 +- number/inRange.js => inRange.js | 23 +- includes.js | 51 ++ array/indexOf.js => indexOf.js | 27 +- array/initial.js => initial.js | 0 internal/Hash.js | 17 + internal/LazyWrapper.js | 6 +- internal/LodashWrapper.js | 7 +- internal/Map.js | 7 + internal/MapCache.js | 21 +- internal/Reflect.js | 6 + internal/Set.js | 7 + internal/SetCache.js | 22 +- internal/Stack.js | 31 + internal/Uint8Array.js | 6 + internal/WeakMap.js | 7 + internal/_Symbol.js | 6 + internal/addMapEntry.js | 14 + internal/addSetEntry.js | 14 + internal/apply.js | 22 + internal/arrayConcat.js | 6 +- internal/arrayEach.js | 4 +- internal/arrayEachRight.js | 2 +- internal/arrayEvery.js | 7 +- internal/arrayExtremum.js | 30 - internal/arrayFilter.js | 4 +- internal/arrayIncludes.js | 16 + internal/arrayIncludesWith.js | 23 + internal/arrayMap.js | 4 +- internal/arrayReduce.js | 7 +- internal/arrayReduceRight.js | 5 +- internal/arraySome.js | 7 +- internal/arraySum.js | 20 - internal/assignDefaults.js | 13 - internal/assignInDefaults.js | 27 + internal/assignMergeValue.js | 18 + internal/assignOwnDefaults.js | 26 - internal/assignValue.js | 28 + internal/assignWith.js | 32 - internal/assocDelete.js | 31 + internal/assocGet.js | 16 + internal/assocHas.js | 15 + internal/assocIndexOf.js | 22 + internal/assocSet.js | 20 + internal/baseAssign.js | 12 +- internal/baseAt.js | 29 +- internal/baseCallback.js | 35 - internal/baseClamp.js | 22 + internal/baseClone.js | 79 +- internal/baseCompareAscending.js | 34 - internal/baseConforms.js | 32 + internal/baseCreate.js | 2 +- internal/baseDelay.js | 4 +- internal/baseDifference.js | 53 +- internal/baseEach.js | 7 +- internal/baseEachRight.js | 7 +- internal/baseEvery.js | 8 +- internal/baseExtremum.js | 37 +- internal/baseFill.js | 13 +- internal/baseFilter.js | 5 +- internal/baseFind.js | 11 +- internal/baseFindIndex.js | 2 +- internal/baseFlatten.js | 12 +- internal/baseForIn.js | 7 +- internal/baseForOwn.js | 7 +- internal/baseForOwnRight.js | 7 +- internal/baseFunctions.js | 18 +- internal/baseGet.js | 19 +- internal/baseHas.js | 26 + internal/baseHasIn.js | 13 + internal/baseInRange.js | 18 + internal/baseIndexOf.js | 2 +- internal/baseIntersection.js | 62 ++ internal/baseInvoke.js | 28 + internal/baseIsEqual.js | 22 +- internal/baseIsEqualDeep.js | 65 +- internal/baseIsFunction.js | 15 - internal/baseIsMatch.js | 24 +- internal/baseIteratee.js | 30 + internal/baseKeys.js | 17 + internal/baseKeysIn.js | 36 + internal/baseMap.js | 7 +- internal/baseMatches.js | 8 +- internal/baseMatchesProperty.js | 43 +- internal/baseMerge.js | 51 +- internal/baseMergeDeep.js | 72 +- internal/baseOrderBy.js | 36 + internal/basePick.js | 22 + internal/basePickBy.js | 21 + internal/basePropertyDeep.js | 5 +- internal/basePullAll.js | 15 + internal/basePullAllBy.js | 43 + internal/basePullAt.js | 31 +- internal/baseRandom.js | 14 +- internal/baseRange.js | 28 + internal/baseReduce.js | 11 +- internal/baseSet.js | 43 + internal/baseSetData.js | 2 +- internal/baseSlice.js | 3 +- internal/baseSome.js | 8 +- internal/baseSortByOrder.js | 31 - .../{binaryIndex.js => baseSortedIndex.js} | 13 +- ...{binaryIndexBy.js => baseSortedIndexBy.js} | 23 +- internal/baseSortedUniq.js | 14 + internal/baseSortedUniqBy.js | 33 + internal/baseSum.js | 23 +- internal/baseTimes.js | 20 + internal/baseToPairs.js | 18 + internal/baseToPath.js | 16 + internal/baseToString.js | 13 - internal/baseUnary.js | 14 + internal/baseUniq.js | 49 +- internal/baseUnset.js | 22 + internal/baseValues.js | 13 +- internal/baseWhile.js | 8 +- internal/baseWrapperValue.js | 14 +- internal/baseXor.js | 30 + internal/bindCallback.js | 39 - internal/bufferClone.js | 22 - internal/cacheHas.js | 25 + internal/cacheIndexOf.js | 19 - internal/cachePush.js | 21 +- internal/charsEndIndex.js | 19 + internal/charsLeftIndex.js | 18 - internal/charsRightIndex.js | 17 - internal/charsStartIndex.js | 20 + internal/checkGlobal.js | 12 + internal/cloneBuffer.js | 19 + internal/cloneMap.js | 17 + internal/cloneRegExp.js | 19 + internal/cloneSet.js | 17 + internal/cloneSymbol.js | 18 + internal/cloneTypedArray.js | 18 + internal/compareAscending.js | 35 +- internal/compareMultiple.js | 16 +- internal/composeArgs.js | 2 +- internal/composeArgsRight.js | 2 +- internal/{arrayCopy.js => copyArray.js} | 4 +- internal/{baseCopy.js => copyObject.js} | 17 +- internal/copyObjectWith.js | 29 + internal/copySymbols.js | 16 + internal/createAggregator.js | 14 +- internal/createAssigner.js | 23 +- internal/createBaseEach.js | 15 +- internal/createBaseFor.js | 14 +- internal/createBaseWrapper.js | 28 + internal/createBindWrapper.js | 23 - internal/createCache.js | 22 - internal/createCaseFirst.js | 34 + internal/createCompounder.js | 18 +- internal/createCtorWrapper.js | 2 +- internal/createCurry.js | 23 - internal/createCurryWrapper.js | 42 + internal/createDefaults.js | 22 - internal/createExtremum.js | 33 - internal/createFind.js | 25 - internal/createFindIndex.js | 21 - internal/createFindKey.js | 18 - internal/createFlow.js | 31 +- internal/createForEach.js | 20 - internal/createForIn.js | 20 - internal/createForOwn.js | 19 - internal/createHybridWrapper.js | 51 +- internal/createObjectMapper.js | 26 - internal/createOver.js | 26 + internal/createPadDir.js | 18 - internal/createPadding.js | 42 +- internal/createPartial.js | 20 - internal/createPartialWrapper.js | 17 +- internal/createRange.js | 31 + internal/createRecurryWrapper.js | 53 ++ internal/createReduce.js | 22 - internal/createRound.js | 19 +- internal/createSet.js | 15 + internal/createSortedIndex.js | 20 - internal/createWrapper.js | 41 +- internal/equalArrays.js | 55 +- internal/equalByTag.js | 50 +- internal/equalObjects.js | 62 +- internal/escapeRegExpChar.js | 38 - internal/getData.js | 2 +- internal/getMatchData.js | 6 +- internal/getNative.js | 2 +- internal/getSymbols.js | 15 + internal/getTag.js | 55 ++ internal/getView.js | 2 +- internal/hasPath.js | 37 + internal/hashDelete.js | 15 + internal/hashGet.js | 28 + internal/hashHas.js | 21 + internal/hashSet.js | 18 + internal/indexKeys.js | 22 + internal/initCloneArray.js | 6 +- internal/initCloneByTag.js | 33 +- internal/initCloneObject.js | 8 +- internal/invokePath.js | 26 - internal/isArrayLike.js | 15 - internal/isHostObject.js | 20 + internal/isIndex.js | 11 +- internal/isIterateeCall.js | 8 +- internal/isKey.js | 16 +- internal/isKeyable.js | 14 + internal/isLaziable.js | 2 +- internal/isLength.js | 20 - internal/isObjectLike.js | 12 - internal/isPrototype.js | 18 + internal/isSpace.js | 14 - internal/isStrictComparable.js | 2 +- internal/iteratorToArray.js | 18 + internal/lazyClone.js | 8 +- internal/lazyValue.js | 4 +- internal/mapClear.js | 15 + internal/mapDelete.js | 17 +- internal/mapGet.js | 17 +- internal/mapHas.js | 19 +- internal/mapSet.js | 24 +- internal/mapToArray.js | 18 + internal/mergeData.js | 29 +- internal/mergeDefaults.js | 22 +- internal/metaMap.js | 6 +- internal/nativeCreate.js | 6 + internal/parent.js | 16 + internal/pickByArray.js | 28 - internal/pickByCallback.js | 22 - internal/reorder.js | 6 +- internal/root.js | 17 +- internal/setData.js | 4 +- internal/setToArray.js | 18 + internal/shimKeys.js | 41 - internal/sortedUniq.js | 29 - internal/stackClear.js | 12 + internal/stackDelete.js | 19 + internal/stackGet.js | 19 + internal/stackHas.js | 19 + internal/stackSet.js | 36 + internal/stringSize.js | 45 + internal/stringToArray.js | 36 + internal/{toPath.js => stringToPath.js} | 18 +- internal/toArrayLikeObject.js | 14 + internal/toFunction.js | 14 + internal/toIterable.js | 22 - internal/toObject.js | 14 - internal/trimmedLeftIndex.js | 19 - internal/trimmedRightIndex.js | 18 - internal/wrapperClone.js | 13 +- intersection.js | 27 + intersectionBy.js | 42 + intersectionWith.js | 40 + object/invert.js => invert.js | 34 +- invoke.js | 23 + collection/invoke.js => invokeMap.js | 25 +- isArguments.js | 43 + isArray.js | 26 + isArrayLike.js | 35 + isArrayLikeObject.js | 32 + lang/isBoolean.js => isBoolean.js | 9 +- lang/isDate.js => isDate.js | 8 +- lang/isElement.js => isElement.js | 4 +- lang/isEmpty.js => isEmpty.js | 20 +- isEqual.js | 34 + isEqualWith.js | 40 + lang/isError.js => isError.js | 9 +- lang/isFinite.js => isFinite.js | 19 +- lang/isFunction.js => isFunction.js | 14 +- isInteger.js | 31 + isLength.js | 32 + isMatch.js | 30 + isMatchWith.js | 40 + lang/isNaN.js => isNaN.js | 2 +- lang/isNative.js => isNative.js | 17 +- isNil.js | 24 + lang/isNull.js => isNull.js | 0 lang/isNumber.js => isNumber.js | 18 +- lang/isObject.js => isObject.js | 5 +- isObjectLike.js | 28 + isPlainObject.js | 68 ++ lang/isRegExp.js => isRegExp.js | 6 +- isSafeInteger.js | 35 + lang/isString.js => isString.js | 10 +- isSymbol.js | 36 + lang/isTypedArray.js => isTypedArray.js | 10 +- lang/isUndefined.js => isUndefined.js | 0 iteratee.js | 41 + join.js | 25 + string/kebabCase.js => kebabCase.js | 2 +- keyBy.js | 34 + keys.js | 55 ++ keysIn.js | 54 ++ lang.default.js | 60 ++ lang.js | 111 +-- lang/clone.js | 70 -- lang/cloneDeep.js | 55 -- lang/eq.js | 2 - lang/isArguments.js | 34 - lang/isArray.js | 40 - lang/isEqual.js | 54 -- lang/isMatch.js | 49 - lang/isPlainObject.js | 71 -- lang/toArray.js | 32 - array/last.js => last.js | 0 array/lastIndexOf.js => lastIndexOf.js | 25 +- lodash.default.js | 604 +++++++++++++ lodash.js | 840 ++++++------------ lowerCase.js | 26 + lowerFirst.js | 21 + lang/lt.js => lt.js | 0 lang/lte.js => lte.js | 0 map.js | 52 ++ object/mapKeys.js => mapKeys.js | 17 +- mapValues.js | 39 + matches.js | 30 + .../matchesProperty.js => matchesProperty.js | 15 +- math.default.js | 18 + math.js | 30 +- math/add.js | 19 - math/max.js | 56 -- math/min.js | 56 -- math/sum.js | 50 -- max.js | 28 + maxBy.js | 33 + mean.js | 20 + function/memoize.js => memoize.js | 47 +- merge.js | 37 + mergeWith.js | 43 + utility/method.js => method.js | 14 +- utility/methodOf.js => methodOf.js | 12 +- min.js | 28 + minBy.js | 33 + mixin.js | 74 ++ function/negate.js => negate.js | 0 next.js | 34 + utility/noop.js => noop.js | 2 +- now.js | 19 + nthArg.js | 25 + number.default.js | 7 + number.js | 11 +- number/random.js | 70 -- object.default.js | 50 ++ object.js | 101 +-- object/assign.js | 43 - object/defaults.js | 25 - object/extend.js | 2 - object/findKey.js | 54 -- object/findLastKey.js | 54 -- object/functions.js | 23 - object/has.js | 57 -- object/keys.js | 45 - object/keysIn.js | 64 -- object/mapValues.js | 46 - object/merge.js | 54 -- object/methods.js | 2 - object/omit.js | 47 - object/pairs.js | 33 - object/pick.js | 42 - object/set.js | 55 -- omit.js | 34 + omitBy.js | 29 + function/once.js => once.js | 4 +- orderBy.js | 45 + over.js | 22 + overArgs.js | 56 ++ overEvery.js | 28 + overSome.js | 28 + package.json | 9 +- string/pad.js => pad.js | 23 +- string/padRight.js => padEnd.js | 16 +- string/padLeft.js => padStart.js | 16 +- string/parseInt.js => parseInt.js | 19 +- function/partial.js => partial.js | 14 +- function/partialRight.js => partialRight.js | 14 +- partition.js | 42 + pick.js | 26 + pickBy.js | 25 + chain/wrapperPlant.js => plant.js | 22 +- utility/property.js => property.js | 13 +- utility/propertyOf.js => propertyOf.js | 9 +- pull.js | 27 + pullAll.js | 28 + pullAllBy.js | 32 + pullAt.js | 40 + random.js | 81 ++ range.js | 45 + rangeRight.js | 39 + function/rearg.js => rearg.js | 16 +- reduce.js | 49 + reduceRight.js | 34 + reject.js | 46 + array/remove.js => remove.js | 27 +- string/repeat.js => repeat.js | 19 +- replace.js | 27 + function/restParam.js => rest.js | 29 +- object/result.js => result.js | 30 +- reverse.js | 31 + math/round.js => round.js | 6 +- sample.js | 25 + sampleSize.js | 38 + seq.default.js | 21 + seq.js | 16 + set.js | 32 + setWith.js | 27 + collection/shuffle.js => shuffle.js | 10 +- size.js | 37 + array/slice.js => slice.js | 13 +- string/snakeCase.js => snakeCase.js | 2 +- some.js | 49 + sortBy.js | 52 ++ sortedIndex.js | 25 + sortedIndexBy.js | 31 + sortedIndexOf.js | 30 + .../sortedLastIndex.js => sortedLastIndex.js | 16 +- sortedLastIndexBy.js | 26 + sortedLastIndexOf.js | 30 + sortedUniq.js | 23 + sortedUniqBy.js | 25 + split.js | 24 + function/spread.js => spread.js | 6 +- string/startCase.js => startCase.js | 5 +- string/startsWith.js => startsWith.js | 14 +- string.default.js | 41 + string.js | 81 +- string/escapeRegExp.js | 32 - string/trim.js | 42 - string/trimLeft.js | 36 - string/trimRight.js | 36 - string/trunc.js | 105 --- string/words.js | 38 - subtract.js | 26 + sum.js | 23 + sumBy.js | 32 + support.js | 10 - array/rest.js => tail.js | 7 +- array/take.js => take.js | 13 +- array/takeRight.js => takeRight.js | 14 +- takeRightWhile.js | 44 + takeWhile.js | 44 + chain/tap.js => tap.js | 13 +- string/template.js => template.js | 39 +- ...templateSettings.js => templateSettings.js | 6 +- function/throttle.js => throttle.js | 25 +- chain/thru.js => thru.js | 7 +- times.js | 50 ++ toArray.js | 57 ++ toInteger.js | 44 + toIterator.js | 22 + toJSON.js | 1 + toLength.js | 36 + toLower.js | 26 + toNumber.js | 59 ++ toPairs.js | 28 + toPairsIn.js | 28 + toPath.js | 34 + lang/toPlainObject.js => toPlainObject.js | 6 +- toSafeInteger.js | 34 + toString.js | 46 + toUpper.js | 26 + object/transform.js => transform.js | 33 +- trim.js | 48 + trimEnd.js | 42 + trimStart.js | 42 + truncate.js | 118 +++ unary.js | 21 + string/unescape.js => unescape.js | 6 +- array/union.js => union.js | 12 +- unionBy.js | 36 + unionWith.js | 34 + uniq.js | 25 + uniqBy.js | 30 + uniqWith.js | 27 + utility/uniqueId.js => uniqueId.js | 6 +- unset.js | 31 + array/unzip.js => unzip.js | 25 +- unzipWith.js | 37 + upperCase.js | 26 + upperFirst.js | 21 + util.default.js | 35 + util.js | 27 + utility.js | 35 - utility/callback.js | 53 -- utility/iteratee.js | 2 - utility/matches.js | 33 - utility/mixin.js | 82 -- utility/range.js | 66 -- utility/times.js | 61 -- value.js | 1 + valueOf.js | 1 + object/values.js => values.js | 4 +- object/valuesIn.js => valuesIn.js | 7 +- array/without.js => without.js | 10 +- words.js | 80 ++ function/wrap.js => wrap.js | 9 +- wrapperAt.js | 48 + chain/wrapperChain.js => wrapperChain.js | 9 +- wrapperFlatMap.js | 22 + wrapperLodash.js | 139 +++ chain/wrapperReverse.js => wrapperReverse.js | 20 +- chain/wrapperValue.js => wrapperValue.js | 4 +- xor.js | 24 + xorBy.js | 36 + xorWith.js | 34 + array/zip.js => zip.js | 4 +- zipObject.js | 30 + zipWith.js | 30 + 675 files changed, 11257 insertions(+), 8085 deletions(-) create mode 100644 add.js rename function/after.js => after.js (73%) create mode 100644 array.default.js delete mode 100644 array/dropRightWhile.js delete mode 100644 array/dropWhile.js delete mode 100644 array/findIndex.js delete mode 100644 array/findLastIndex.js delete mode 100644 array/flatten.js delete mode 100644 array/head.js delete mode 100644 array/intersection.js delete mode 100644 array/object.js delete mode 100644 array/pull.js delete mode 100644 array/pullAt.js delete mode 100644 array/sortedIndex.js delete mode 100644 array/tail.js delete mode 100644 array/takeRightWhile.js delete mode 100644 array/takeWhile.js delete mode 100644 array/uniq.js delete mode 100644 array/unique.js delete mode 100644 array/unzipWith.js delete mode 100644 array/xor.js delete mode 100644 array/zipObject.js delete mode 100644 array/zipWith.js rename function/ary.js => ary.js (51%) create mode 100644 assign.js create mode 100644 assignIn.js create mode 100644 assignInWith.js create mode 100644 assignWith.js create mode 100644 at.js rename utility/attempt.js => attempt.js (74%) rename function/before.js => before.js (81%) rename function/bind.js => bind.js (79%) create mode 100644 bindAll.js rename function/bindKey.js => bindKey.js (83%) rename string/camelCase.js => camelCase.js (77%) rename string/capitalize.js => capitalize.js (51%) rename math/ceil.js => ceil.js (69%) delete mode 100644 chain/chain.js delete mode 100644 chain/commit.js delete mode 100644 chain/concat.js delete mode 100644 chain/lodash.js delete mode 100644 chain/plant.js delete mode 100644 chain/reverse.js delete mode 100644 chain/run.js delete mode 100644 chain/toJSON.js delete mode 100644 chain/toString.js delete mode 100644 chain/value.js delete mode 100644 chain/valueOf.js delete mode 100644 chain/wrapperConcat.js delete mode 100644 chain/wrapperToString.js rename array/chunk.js => chunk.js (51%) create mode 100644 clamp.js create mode 100644 clone.js create mode 100644 cloneDeep.js create mode 100644 cloneDeepWith.js create mode 100644 cloneWith.js create mode 100644 collection.default.js delete mode 100644 collection/all.js delete mode 100644 collection/any.js delete mode 100644 collection/at.js delete mode 100644 collection/collect.js delete mode 100644 collection/contains.js delete mode 100644 collection/countBy.js delete mode 100644 collection/detect.js delete mode 100644 collection/each.js delete mode 100644 collection/eachRight.js delete mode 100644 collection/every.js delete mode 100644 collection/filter.js delete mode 100644 collection/find.js delete mode 100644 collection/findLast.js delete mode 100644 collection/findWhere.js delete mode 100644 collection/foldl.js delete mode 100644 collection/foldr.js delete mode 100644 collection/forEach.js delete mode 100644 collection/forEachRight.js delete mode 100644 collection/groupBy.js delete mode 100644 collection/include.js delete mode 100644 collection/includes.js delete mode 100644 collection/indexBy.js delete mode 100644 collection/inject.js delete mode 100644 collection/map.js delete mode 100644 collection/max.js delete mode 100644 collection/min.js delete mode 100644 collection/partition.js delete mode 100644 collection/pluck.js delete mode 100644 collection/reduce.js delete mode 100644 collection/reduceRight.js delete mode 100644 collection/reject.js delete mode 100644 collection/sample.js delete mode 100644 collection/select.js delete mode 100644 collection/size.js delete mode 100644 collection/some.js delete mode 100644 collection/sortBy.js delete mode 100644 collection/sortByAll.js delete mode 100644 collection/sortByOrder.js delete mode 100644 collection/sum.js delete mode 100644 collection/where.js rename chain/wrapperCommit.js => commit.js (88%) rename array/compact.js => compact.js (100%) create mode 100644 concat.js create mode 100644 cond.js create mode 100644 conforms.js rename utility/constant.js => constant.js (95%) create mode 100644 countBy.js rename object/create.js => create.js (55%) create mode 100644 curry.js rename function/curryRight.js => curryRight.js (66%) create mode 100644 date.default.js delete mode 100644 date/now.js rename function/debounce.js => debounce.js (73%) rename string/deburr.js => deburr.js (71%) create mode 100644 defaults.js rename object/defaultsDeep.js => defaultsDeep.js (65%) rename function/defer.js => defer.js (71%) rename function/delay.js => delay.js (64%) rename array/difference.js => difference.js (50%) create mode 100644 differenceBy.js create mode 100644 differenceWith.js rename array/drop.js => drop.js (66%) rename array/dropRight.js => dropRight.js (69%) create mode 100644 dropRightWhile.js create mode 100644 dropWhile.js create mode 100644 each.js create mode 100644 eachRight.js rename string/endsWith.js => endsWith.js (73%) create mode 100644 eq.js rename string/escape.js => escape.js (72%) create mode 100644 escapeRegExp.js create mode 100644 every.js rename array/fill.js => fill.js (84%) create mode 100644 filter.js create mode 100644 find.js create mode 100644 findIndex.js create mode 100644 findKey.js create mode 100644 findLast.js create mode 100644 findLastIndex.js create mode 100644 findLastKey.js create mode 100644 flatMap.js create mode 100644 flatten.js rename array/flattenDeep.js => flattenDeep.js (75%) create mode 100644 flip.js rename math/floor.js => floor.js (70%) rename function/flow.js => flow.js (78%) rename function/flowRight.js => flowRight.js (73%) create mode 100644 forEach.js create mode 100644 forEachRight.js rename object/forIn.js => forIn.js (50%) rename object/forInRight.js => forInRight.js (62%) rename object/forOwn.js => forOwn.js (52%) rename object/forOwnRight.js => forOwnRight.js (66%) create mode 100644 fromPairs.js create mode 100644 function.default.js delete mode 100644 function/backflow.js delete mode 100644 function/bindAll.js delete mode 100644 function/compose.js delete mode 100644 function/curry.js delete mode 100644 function/modArgs.js create mode 100644 functions.js create mode 100644 functionsIn.js rename object/get.js => get.js (73%) create mode 100644 groupBy.js rename lang/gt.js => gt.js (100%) rename lang/gte.js => gte.js (100%) create mode 100644 has.js create mode 100644 hasIn.js rename array/first.js => head.js (73%) rename utility/identity.js => identity.js (94%) rename number/inRange.js => inRange.js (55%) create mode 100644 includes.js rename array/indexOf.js => indexOf.js (53%) rename array/initial.js => initial.js (100%) create mode 100644 internal/Hash.js create mode 100644 internal/Map.js create mode 100644 internal/Reflect.js create mode 100644 internal/Set.js create mode 100644 internal/Stack.js create mode 100644 internal/Uint8Array.js create mode 100644 internal/WeakMap.js create mode 100644 internal/_Symbol.js create mode 100644 internal/addMapEntry.js create mode 100644 internal/addSetEntry.js create mode 100644 internal/apply.js delete mode 100644 internal/arrayExtremum.js create mode 100644 internal/arrayIncludes.js create mode 100644 internal/arrayIncludesWith.js delete mode 100644 internal/arraySum.js delete mode 100644 internal/assignDefaults.js create mode 100644 internal/assignInDefaults.js create mode 100644 internal/assignMergeValue.js delete mode 100644 internal/assignOwnDefaults.js create mode 100644 internal/assignValue.js delete mode 100644 internal/assignWith.js create mode 100644 internal/assocDelete.js create mode 100644 internal/assocGet.js create mode 100644 internal/assocHas.js create mode 100644 internal/assocIndexOf.js create mode 100644 internal/assocSet.js delete mode 100644 internal/baseCallback.js create mode 100644 internal/baseClamp.js delete mode 100644 internal/baseCompareAscending.js create mode 100644 internal/baseConforms.js create mode 100644 internal/baseHas.js create mode 100644 internal/baseHasIn.js create mode 100644 internal/baseInRange.js create mode 100644 internal/baseIntersection.js create mode 100644 internal/baseInvoke.js delete mode 100644 internal/baseIsFunction.js create mode 100644 internal/baseIteratee.js create mode 100644 internal/baseKeys.js create mode 100644 internal/baseKeysIn.js create mode 100644 internal/baseOrderBy.js create mode 100644 internal/basePick.js create mode 100644 internal/basePickBy.js create mode 100644 internal/basePullAll.js create mode 100644 internal/basePullAllBy.js create mode 100644 internal/baseRange.js create mode 100644 internal/baseSet.js delete mode 100644 internal/baseSortByOrder.js rename internal/{binaryIndex.js => baseSortedIndex.js} (71%) rename internal/{binaryIndexBy.js => baseSortedIndexBy.js} (73%) create mode 100644 internal/baseSortedUniq.js create mode 100644 internal/baseSortedUniqBy.js create mode 100644 internal/baseTimes.js create mode 100644 internal/baseToPairs.js create mode 100644 internal/baseToPath.js delete mode 100644 internal/baseToString.js create mode 100644 internal/baseUnary.js create mode 100644 internal/baseUnset.js create mode 100644 internal/baseXor.js delete mode 100644 internal/bindCallback.js delete mode 100644 internal/bufferClone.js create mode 100644 internal/cacheHas.js delete mode 100644 internal/cacheIndexOf.js create mode 100644 internal/charsEndIndex.js delete mode 100644 internal/charsLeftIndex.js delete mode 100644 internal/charsRightIndex.js create mode 100644 internal/charsStartIndex.js create mode 100644 internal/checkGlobal.js create mode 100644 internal/cloneBuffer.js create mode 100644 internal/cloneMap.js create mode 100644 internal/cloneRegExp.js create mode 100644 internal/cloneSet.js create mode 100644 internal/cloneSymbol.js create mode 100644 internal/cloneTypedArray.js rename internal/{arrayCopy.js => copyArray.js} (86%) rename internal/{baseCopy.js => copyObject.js} (53%) create mode 100644 internal/copyObjectWith.js create mode 100644 internal/copySymbols.js create mode 100644 internal/createBaseWrapper.js delete mode 100644 internal/createBindWrapper.js delete mode 100644 internal/createCache.js create mode 100644 internal/createCaseFirst.js delete mode 100644 internal/createCurry.js create mode 100644 internal/createCurryWrapper.js delete mode 100644 internal/createDefaults.js delete mode 100644 internal/createExtremum.js delete mode 100644 internal/createFind.js delete mode 100644 internal/createFindIndex.js delete mode 100644 internal/createFindKey.js delete mode 100644 internal/createForEach.js delete mode 100644 internal/createForIn.js delete mode 100644 internal/createForOwn.js delete mode 100644 internal/createObjectMapper.js create mode 100644 internal/createOver.js delete mode 100644 internal/createPadDir.js delete mode 100644 internal/createPartial.js create mode 100644 internal/createRange.js create mode 100644 internal/createRecurryWrapper.js delete mode 100644 internal/createReduce.js create mode 100644 internal/createSet.js delete mode 100644 internal/createSortedIndex.js delete mode 100644 internal/escapeRegExpChar.js create mode 100644 internal/getSymbols.js create mode 100644 internal/getTag.js create mode 100644 internal/hasPath.js create mode 100644 internal/hashDelete.js create mode 100644 internal/hashGet.js create mode 100644 internal/hashHas.js create mode 100644 internal/hashSet.js create mode 100644 internal/indexKeys.js delete mode 100644 internal/invokePath.js delete mode 100644 internal/isArrayLike.js create mode 100644 internal/isHostObject.js create mode 100644 internal/isKeyable.js delete mode 100644 internal/isLength.js delete mode 100644 internal/isObjectLike.js create mode 100644 internal/isPrototype.js delete mode 100644 internal/isSpace.js create mode 100644 internal/iteratorToArray.js create mode 100644 internal/mapClear.js create mode 100644 internal/mapToArray.js create mode 100644 internal/nativeCreate.js create mode 100644 internal/parent.js delete mode 100644 internal/pickByArray.js delete mode 100644 internal/pickByCallback.js create mode 100644 internal/setToArray.js delete mode 100644 internal/shimKeys.js delete mode 100644 internal/sortedUniq.js create mode 100644 internal/stackClear.js create mode 100644 internal/stackDelete.js create mode 100644 internal/stackGet.js create mode 100644 internal/stackHas.js create mode 100644 internal/stackSet.js create mode 100644 internal/stringSize.js create mode 100644 internal/stringToArray.js rename internal/{toPath.js => stringToPath.js} (51%) create mode 100644 internal/toArrayLikeObject.js create mode 100644 internal/toFunction.js delete mode 100644 internal/toIterable.js delete mode 100644 internal/toObject.js delete mode 100644 internal/trimmedLeftIndex.js delete mode 100644 internal/trimmedRightIndex.js create mode 100644 intersection.js create mode 100644 intersectionBy.js create mode 100644 intersectionWith.js rename object/invert.js => invert.js (55%) create mode 100644 invoke.js rename collection/invoke.js => invokeMap.js (59%) create mode 100644 isArguments.js create mode 100644 isArray.js create mode 100644 isArrayLike.js create mode 100644 isArrayLikeObject.js rename lang/isBoolean.js => isBoolean.js (72%) rename lang/isDate.js => isDate.js (76%) rename lang/isElement.js => isElement.js (83%) rename lang/isEmpty.js => isEmpty.js (58%) create mode 100644 isEqual.js create mode 100644 isEqualWith.js rename lang/isError.js => isError.js (74%) rename lang/isFinite.js => isFinite.js (54%) rename lang/isFunction.js => isFunction.js (63%) create mode 100644 isInteger.js create mode 100644 isLength.js create mode 100644 isMatch.js create mode 100644 isMatchWith.js rename lang/isNaN.js => isNaN.js (96%) rename lang/isNative.js => isNative.js (63%) create mode 100644 isNil.js rename lang/isNull.js => isNull.js (100%) rename lang/isNumber.js => isNumber.js (68%) rename lang/isObject.js => isObject.js (92%) create mode 100644 isObjectLike.js create mode 100644 isPlainObject.js rename lang/isRegExp.js => isRegExp.js (81%) create mode 100644 isSafeInteger.js rename lang/isString.js => isString.js (69%) create mode 100644 isSymbol.js rename lang/isTypedArray.js => isTypedArray.js (91%) rename lang/isUndefined.js => isUndefined.js (100%) create mode 100644 iteratee.js create mode 100644 join.js rename string/kebabCase.js => kebabCase.js (90%) create mode 100644 keyBy.js create mode 100644 keys.js create mode 100644 keysIn.js create mode 100644 lang.default.js delete mode 100644 lang/clone.js delete mode 100644 lang/cloneDeep.js delete mode 100644 lang/eq.js delete mode 100644 lang/isArguments.js delete mode 100644 lang/isArray.js delete mode 100644 lang/isEqual.js delete mode 100644 lang/isMatch.js delete mode 100644 lang/isPlainObject.js delete mode 100644 lang/toArray.js rename array/last.js => last.js (100%) rename array/lastIndexOf.js => lastIndexOf.js (52%) create mode 100644 lodash.default.js create mode 100644 lowerCase.js create mode 100644 lowerFirst.js rename lang/lt.js => lt.js (100%) rename lang/lte.js => lte.js (100%) create mode 100644 map.js rename object/mapKeys.js => mapKeys.js (62%) create mode 100644 mapValues.js create mode 100644 matches.js rename utility/matchesProperty.js => matchesProperty.js (53%) create mode 100644 math.default.js delete mode 100644 math/add.js delete mode 100644 math/max.js delete mode 100644 math/min.js delete mode 100644 math/sum.js create mode 100644 max.js create mode 100644 maxBy.js create mode 100644 mean.js rename function/memoize.js => memoize.js (66%) create mode 100644 merge.js create mode 100644 mergeWith.js rename utility/method.js => method.js (62%) rename utility/methodOf.js => methodOf.js (69%) create mode 100644 min.js create mode 100644 minBy.js create mode 100644 mixin.js rename function/negate.js => negate.js (100%) create mode 100644 next.js rename utility/noop.js => noop.js (93%) create mode 100644 now.js create mode 100644 nthArg.js create mode 100644 number.default.js delete mode 100644 number/random.js create mode 100644 object.default.js delete mode 100644 object/assign.js delete mode 100644 object/defaults.js delete mode 100644 object/extend.js delete mode 100644 object/findKey.js delete mode 100644 object/findLastKey.js delete mode 100644 object/functions.js delete mode 100644 object/has.js delete mode 100644 object/keys.js delete mode 100644 object/keysIn.js delete mode 100644 object/mapValues.js delete mode 100644 object/merge.js delete mode 100644 object/methods.js delete mode 100644 object/omit.js delete mode 100644 object/pairs.js delete mode 100644 object/pick.js delete mode 100644 object/set.js create mode 100644 omit.js create mode 100644 omitBy.js rename function/once.js => once.js (77%) create mode 100644 orderBy.js create mode 100644 over.js create mode 100644 overArgs.js create mode 100644 overEvery.js create mode 100644 overSome.js rename string/pad.js => pad.js (59%) rename string/padRight.js => padEnd.js (59%) rename string/padLeft.js => padStart.js (58%) rename string/parseInt.js => parseInt.js (69%) rename function/partial.js => partial.js (72%) rename function/partialRight.js => partialRight.js (70%) create mode 100644 partition.js create mode 100644 pick.js create mode 100644 pickBy.js rename chain/wrapperPlant.js => plant.js (64%) rename utility/property.js => property.js (58%) rename utility/propertyOf.js => propertyOf.js (72%) create mode 100644 pull.js create mode 100644 pullAll.js create mode 100644 pullAllBy.js create mode 100644 pullAt.js create mode 100644 random.js create mode 100644 range.js create mode 100644 rangeRight.js rename function/rearg.js => rearg.js (70%) create mode 100644 reduce.js create mode 100644 reduceRight.js create mode 100644 reject.js rename array/remove.js => remove.js (53%) rename string/repeat.js => repeat.js (67%) create mode 100644 replace.js rename function/restParam.js => rest.js (64%) rename object/result.js => result.js (55%) create mode 100644 reverse.js rename math/round.js => round.js (70%) create mode 100644 sample.js create mode 100644 sampleSize.js create mode 100644 seq.default.js create mode 100644 seq.js create mode 100644 set.js create mode 100644 setWith.js rename collection/shuffle.js => shuffle.js (59%) create mode 100644 size.js rename array/slice.js => slice.js (61%) rename string/snakeCase.js => snakeCase.js (90%) create mode 100644 some.js create mode 100644 sortBy.js create mode 100644 sortedIndex.js create mode 100644 sortedIndexBy.js create mode 100644 sortedIndexOf.js rename array/sortedLastIndex.js => sortedLastIndex.js (55%) create mode 100644 sortedLastIndexBy.js create mode 100644 sortedLastIndexOf.js create mode 100644 sortedUniq.js create mode 100644 sortedUniqBy.js create mode 100644 split.js rename function/spread.js => spread.js (90%) rename string/startCase.js => startCase.js (77%) rename string/startsWith.js => startsWith.js (68%) create mode 100644 string.default.js delete mode 100644 string/escapeRegExp.js delete mode 100644 string/trim.js delete mode 100644 string/trimLeft.js delete mode 100644 string/trimRight.js delete mode 100644 string/trunc.js delete mode 100644 string/words.js create mode 100644 subtract.js create mode 100644 sum.js create mode 100644 sumBy.js delete mode 100644 support.js rename array/rest.js => tail.js (77%) rename array/take.js => take.js (64%) rename array/takeRight.js => takeRight.js (65%) create mode 100644 takeRightWhile.js create mode 100644 takeWhile.js rename chain/tap.js => tap.js (54%) rename string/template.js => template.js (87%) rename string/templateSettings.js => templateSettings.js (89%) rename function/throttle.js => throttle.js (71%) rename chain/thru.js => thru.js (73%) create mode 100644 times.js create mode 100644 toArray.js create mode 100644 toInteger.js create mode 100644 toIterator.js create mode 100644 toJSON.js create mode 100644 toLength.js create mode 100644 toLower.js create mode 100644 toNumber.js create mode 100644 toPairs.js create mode 100644 toPairsIn.js create mode 100644 toPath.js rename lang/toPlainObject.js => toPlainObject.js (82%) create mode 100644 toSafeInteger.js create mode 100644 toString.js create mode 100644 toUpper.js rename object/transform.js => transform.js (58%) create mode 100644 trim.js create mode 100644 trimEnd.js create mode 100644 trimStart.js create mode 100644 truncate.js create mode 100644 unary.js rename string/unescape.js => unescape.js (86%) rename array/union.js => union.js (66%) create mode 100644 unionBy.js create mode 100644 unionWith.js create mode 100644 uniq.js create mode 100644 uniqBy.js create mode 100644 uniqWith.js rename utility/uniqueId.js => uniqueId.js (80%) create mode 100644 unset.js rename array/unzip.js => unzip.js (62%) create mode 100644 unzipWith.js create mode 100644 upperCase.js create mode 100644 upperFirst.js create mode 100644 util.default.js create mode 100644 util.js delete mode 100644 utility.js delete mode 100644 utility/callback.js delete mode 100644 utility/iteratee.js delete mode 100644 utility/matches.js delete mode 100644 utility/mixin.js delete mode 100644 utility/range.js delete mode 100644 utility/times.js create mode 100644 value.js create mode 100644 valueOf.js rename object/values.js => values.js (84%) rename object/valuesIn.js => valuesIn.js (80%) rename array/without.js => without.js (69%) create mode 100644 words.js rename function/wrap.js => wrap.js (75%) create mode 100644 wrapperAt.js rename chain/wrapperChain.js => wrapperChain.js (88%) create mode 100644 wrapperFlatMap.js create mode 100644 wrapperLodash.js rename chain/wrapperReverse.js => wrapperReverse.js (52%) rename chain/wrapperValue.js => wrapperValue.js (82%) create mode 100644 xor.js create mode 100644 xorBy.js create mode 100644 xorWith.js rename array/zip.js => zip.js (87%) create mode 100644 zipObject.js create mode 100644 zipWith.js diff --git a/LICENSE b/LICENSE index 9cd87e5dc..b054ca5a3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright 2012-2015 The Dojo Foundation -Based on Underscore.js, copyright 2009-2015 Jeremy Ashkenas, +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index 240120651..ccfaa3d45 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# lodash-es v3.10.1 +# lodash-es v4.0.0 -The [modern build](https://github.com/lodash/lodash/wiki/Build-Differences) of [lodash](https://lodash.com/) exported as [ES](https://people.mozilla.org/~jorendorff/es6-draft.html) modules. +The [lodash](https://lodash.com/) library exported as [ES](http://www.ecma-international.org/ecma-262/6.0/) modules. Generated using [lodash-cli](https://www.npmjs.com/package/lodash-cli): ```bash -$ lodash modularize modern exports=es -o ./ +$ lodash modularize exports=es -o ./ ``` -See the [package source](https://github.com/lodash/lodash/tree/3.10.1-es) for more details. +See the [package source](https://github.com/lodash/lodash/tree/4.0.0-es) for more details. diff --git a/add.js b/add.js new file mode 100644 index 000000000..2a6fcb142 --- /dev/null +++ b/add.js @@ -0,0 +1,26 @@ +/** + * Adds two numbers. + * + * @static + * @memberOf _ + * @category Math + * @param {number} augend The first number in an addition. + * @param {number} addend The second number in an addition. + * @returns {number} Returns the total. + * @example + * + * _.add(6, 4); + * // => 10 + */ +function add(augend, addend) { + var result; + if (augend !== undefined) { + result = augend; + } + if (addend !== undefined) { + result = result === undefined ? addend : (result + addend); + } + return result; +} + +export default add; diff --git a/function/after.js b/after.js similarity index 73% rename from function/after.js rename to after.js index ab87ab206..4878c7b6f 100644 --- a/function/after.js +++ b/after.js @@ -1,11 +1,8 @@ -import root from '../internal/root'; +import toInteger from './toInteger'; /** 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 nativeIsFinite = root.isFinite; - /** * The opposite of `_.before`; this method creates a function that invokes * `func` once it's called `n` or more times. @@ -31,15 +28,9 @@ var nativeIsFinite = root.isFinite; */ function after(n, func) { if (typeof func != 'function') { - if (typeof n == 'function') { - var temp = n; - n = func; - func = temp; - } else { - throw new TypeError(FUNC_ERROR_TEXT); - } + throw new TypeError(FUNC_ERROR_TEXT); } - n = nativeIsFinite(n = +n) ? n : 0; + n = toInteger(n); return function() { if (--n < 1) { return func.apply(this, arguments); diff --git a/array.default.js b/array.default.js new file mode 100644 index 000000000..38a07bdc4 --- /dev/null +++ b/array.default.js @@ -0,0 +1,77 @@ +import chunk from './chunk'; +import compact from './compact'; +import concat from './concat'; +import difference from './difference'; +import differenceBy from './differenceBy'; +import differenceWith from './differenceWith'; +import drop from './drop'; +import dropRight from './dropRight'; +import dropRightWhile from './dropRightWhile'; +import dropWhile from './dropWhile'; +import fill from './fill'; +import findIndex from './findIndex'; +import findLastIndex from './findLastIndex'; +import flatMap from './flatMap'; +import flatten from './flatten'; +import flattenDeep from './flattenDeep'; +import fromPairs from './fromPairs'; +import head from './head'; +import indexOf from './indexOf'; +import initial from './initial'; +import intersection from './intersection'; +import intersectionBy from './intersectionBy'; +import intersectionWith from './intersectionWith'; +import join from './join'; +import last from './last'; +import lastIndexOf from './lastIndexOf'; +import pull from './pull'; +import pullAll from './pullAll'; +import pullAllBy from './pullAllBy'; +import pullAt from './pullAt'; +import remove from './remove'; +import reverse from './reverse'; +import slice from './slice'; +import sortedIndex from './sortedIndex'; +import sortedIndexBy from './sortedIndexBy'; +import sortedIndexOf from './sortedIndexOf'; +import sortedLastIndex from './sortedLastIndex'; +import sortedLastIndexBy from './sortedLastIndexBy'; +import sortedLastIndexOf from './sortedLastIndexOf'; +import sortedUniq from './sortedUniq'; +import sortedUniqBy from './sortedUniqBy'; +import tail from './tail'; +import take from './take'; +import takeRight from './takeRight'; +import takeRightWhile from './takeRightWhile'; +import takeWhile from './takeWhile'; +import union from './union'; +import unionBy from './unionBy'; +import unionWith from './unionWith'; +import uniq from './uniq'; +import uniqBy from './uniqBy'; +import uniqWith from './uniqWith'; +import unzip from './unzip'; +import unzipWith from './unzipWith'; +import without from './without'; +import xor from './xor'; +import xorBy from './xorBy'; +import xorWith from './xorWith'; +import zip from './zip'; +import zipObject from './zipObject'; +import zipWith from './zipWith'; + +export default { + chunk, compact, concat, difference, differenceBy, + differenceWith, drop, dropRight, dropRightWhile, dropWhile, + fill, findIndex, findLastIndex, flatMap, flatten, + flattenDeep, fromPairs, head, indexOf, initial, + intersection, intersectionBy, intersectionWith, join, last, + lastIndexOf, pull, pullAll, pullAllBy, pullAt, + remove, reverse, slice, sortedIndex, sortedIndexBy, + sortedIndexOf, sortedLastIndex, sortedLastIndexBy, sortedLastIndexOf, sortedUniq, + sortedUniqBy, tail, take, takeRight, takeRightWhile, + takeWhile, union, unionBy, unionWith, uniq, + uniqBy, uniqWith, unzip, unzipWith, without, + xor, xorBy, xorWith, zip, zipObject, + zipWith +}; diff --git a/array.js b/array.js index b1f14a58d..56cd7d9ab 100644 --- a/array.js +++ b/array.js @@ -1,87 +1,62 @@ -import chunk from './array/chunk'; -import compact from './array/compact'; -import difference from './array/difference'; -import drop from './array/drop'; -import dropRight from './array/dropRight'; -import dropRightWhile from './array/dropRightWhile'; -import dropWhile from './array/dropWhile'; -import fill from './array/fill'; -import findIndex from './array/findIndex'; -import findLastIndex from './array/findLastIndex'; -import first from './array/first'; -import flatten from './array/flatten'; -import flattenDeep from './array/flattenDeep'; -import head from './array/head'; -import indexOf from './array/indexOf'; -import initial from './array/initial'; -import intersection from './array/intersection'; -import last from './array/last'; -import lastIndexOf from './array/lastIndexOf'; -import object from './array/object'; -import pull from './array/pull'; -import pullAt from './array/pullAt'; -import remove from './array/remove'; -import rest from './array/rest'; -import slice from './array/slice'; -import sortedIndex from './array/sortedIndex'; -import sortedLastIndex from './array/sortedLastIndex'; -import tail from './array/tail'; -import take from './array/take'; -import takeRight from './array/takeRight'; -import takeRightWhile from './array/takeRightWhile'; -import takeWhile from './array/takeWhile'; -import union from './array/union'; -import uniq from './array/uniq'; -import unique from './array/unique'; -import unzip from './array/unzip'; -import unzipWith from './array/unzipWith'; -import without from './array/without'; -import xor from './array/xor'; -import zip from './array/zip'; -import zipObject from './array/zipObject'; -import zipWith from './array/zipWith'; - -export default { - 'chunk': chunk, - 'compact': compact, - 'difference': difference, - 'drop': drop, - 'dropRight': dropRight, - 'dropRightWhile': dropRightWhile, - 'dropWhile': dropWhile, - 'fill': fill, - 'findIndex': findIndex, - 'findLastIndex': findLastIndex, - 'first': first, - 'flatten': flatten, - 'flattenDeep': flattenDeep, - 'head': head, - 'indexOf': indexOf, - 'initial': initial, - 'intersection': intersection, - 'last': last, - 'lastIndexOf': lastIndexOf, - 'object': object, - 'pull': pull, - 'pullAt': pullAt, - 'remove': remove, - 'rest': rest, - 'slice': slice, - 'sortedIndex': sortedIndex, - 'sortedLastIndex': sortedLastIndex, - 'tail': tail, - 'take': take, - 'takeRight': takeRight, - 'takeRightWhile': takeRightWhile, - 'takeWhile': takeWhile, - 'union': union, - 'uniq': uniq, - 'unique': unique, - 'unzip': unzip, - 'unzipWith': unzipWith, - 'without': without, - 'xor': xor, - 'zip': zip, - 'zipObject': zipObject, - 'zipWith': zipWith -}; +export { default as chunk } from './chunk'; +export { default as compact } from './compact'; +export { default as concat } from './concat'; +export { default as difference } from './difference'; +export { default as differenceBy } from './differenceBy'; +export { default as differenceWith } from './differenceWith'; +export { default as drop } from './drop'; +export { default as dropRight } from './dropRight'; +export { default as dropRightWhile } from './dropRightWhile'; +export { default as dropWhile } from './dropWhile'; +export { default as fill } from './fill'; +export { default as findIndex } from './findIndex'; +export { default as findLastIndex } from './findLastIndex'; +export { default as flatMap } from './flatMap'; +export { default as flatten } from './flatten'; +export { default as flattenDeep } from './flattenDeep'; +export { default as fromPairs } from './fromPairs'; +export { default as head } from './head'; +export { default as indexOf } from './indexOf'; +export { default as initial } from './initial'; +export { default as intersection } from './intersection'; +export { default as intersectionBy } from './intersectionBy'; +export { default as intersectionWith } from './intersectionWith'; +export { default as join } from './join'; +export { default as last } from './last'; +export { default as lastIndexOf } from './lastIndexOf'; +export { default as pull } from './pull'; +export { default as pullAll } from './pullAll'; +export { default as pullAllBy } from './pullAllBy'; +export { default as pullAt } from './pullAt'; +export { default as remove } from './remove'; +export { default as reverse } from './reverse'; +export { default as slice } from './slice'; +export { default as sortedIndex } from './sortedIndex'; +export { default as sortedIndexBy } from './sortedIndexBy'; +export { default as sortedIndexOf } from './sortedIndexOf'; +export { default as sortedLastIndex } from './sortedLastIndex'; +export { default as sortedLastIndexBy } from './sortedLastIndexBy'; +export { default as sortedLastIndexOf } from './sortedLastIndexOf'; +export { default as sortedUniq } from './sortedUniq'; +export { default as sortedUniqBy } from './sortedUniqBy'; +export { default as tail } from './tail'; +export { default as take } from './take'; +export { default as takeRight } from './takeRight'; +export { default as takeRightWhile } from './takeRightWhile'; +export { default as takeWhile } from './takeWhile'; +export { default as union } from './union'; +export { default as unionBy } from './unionBy'; +export { default as unionWith } from './unionWith'; +export { default as uniq } from './uniq'; +export { default as uniqBy } from './uniqBy'; +export { default as uniqWith } from './uniqWith'; +export { default as unzip } from './unzip'; +export { default as unzipWith } from './unzipWith'; +export { default as without } from './without'; +export { default as xor } from './xor'; +export { default as xorBy } from './xorBy'; +export { default as xorWith } from './xorWith'; +export { default as zip } from './zip'; +export { default as zipObject } from './zipObject'; +export { default as zipWith } from './zipWith'; +export { default as default } from './array.default'; diff --git a/array/dropRightWhile.js b/array/dropRightWhile.js deleted file mode 100644 index a3e52158d..000000000 --- a/array/dropRightWhile.js +++ /dev/null @@ -1,59 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import baseWhile from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that match the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.dropRightWhile([1, 2, 3], function(n) { - * return n > 1; - * }); - * // => [1] - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': false } - * ]; - * - * // using the `_.matches` callback shorthand - * _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user'); - * // => ['barney', 'fred'] - * - * // using the `_.matchesProperty` callback shorthand - * _.pluck(_.dropRightWhile(users, 'active', false), 'user'); - * // => ['barney'] - * - * // using the `_.property` callback shorthand - * _.pluck(_.dropRightWhile(users, 'active'), 'user'); - * // => ['barney', 'fred', 'pebbles'] - */ -function dropRightWhile(array, predicate, thisArg) { - return (array && array.length) - ? baseWhile(array, baseCallback(predicate, thisArg, 3), true, true) - : []; -} - -export default dropRightWhile; diff --git a/array/dropWhile.js b/array/dropWhile.js deleted file mode 100644 index 289897670..000000000 --- a/array/dropWhile.js +++ /dev/null @@ -1,59 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import baseWhile from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.dropWhile([1, 2, 3], function(n) { - * return n < 3; - * }); - * // => [3] - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * // using the `_.matches` callback shorthand - * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user'); - * // => ['fred', 'pebbles'] - * - * // using the `_.matchesProperty` callback shorthand - * _.pluck(_.dropWhile(users, 'active', false), 'user'); - * // => ['pebbles'] - * - * // using the `_.property` callback shorthand - * _.pluck(_.dropWhile(users, 'active'), 'user'); - * // => ['barney', 'fred', 'pebbles'] - */ -function dropWhile(array, predicate, thisArg) { - return (array && array.length) - ? baseWhile(array, baseCallback(predicate, thisArg, 3), true) - : []; -} - -export default dropWhile; diff --git a/array/findIndex.js b/array/findIndex.js deleted file mode 100644 index 1c42d41f5..000000000 --- a/array/findIndex.js +++ /dev/null @@ -1,53 +0,0 @@ -import createFindIndex from '../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. - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {number} Returns the index of the found element, else `-1`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * _.findIndex(users, function(chr) { - * return chr.user == 'barney'; - * }); - * // => 0 - * - * // using the `_.matches` callback shorthand - * _.findIndex(users, { 'user': 'fred', 'active': false }); - * // => 1 - * - * // using the `_.matchesProperty` callback shorthand - * _.findIndex(users, 'active', false); - * // => 0 - * - * // using the `_.property` callback shorthand - * _.findIndex(users, 'active'); - * // => 2 - */ -var findIndex = createFindIndex(); - -export default findIndex; diff --git a/array/findLastIndex.js b/array/findLastIndex.js deleted file mode 100644 index a34e60821..000000000 --- a/array/findLastIndex.js +++ /dev/null @@ -1,53 +0,0 @@ -import createFindIndex from '../internal/createFindIndex'; - -/** - * This method is like `_.findIndex` except that it iterates over elements - * of `collection` from right to left. - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {number} Returns the index of the found element, else `-1`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': false } - * ]; - * - * _.findLastIndex(users, function(chr) { - * return chr.user == 'pebbles'; - * }); - * // => 2 - * - * // using the `_.matches` callback shorthand - * _.findLastIndex(users, { 'user': 'barney', 'active': true }); - * // => 0 - * - * // using the `_.matchesProperty` callback shorthand - * _.findLastIndex(users, 'active', false); - * // => 2 - * - * // using the `_.property` callback shorthand - * _.findLastIndex(users, 'active'); - * // => 0 - */ -var findLastIndex = createFindIndex(true); - -export default findLastIndex; diff --git a/array/flatten.js b/array/flatten.js deleted file mode 100644 index 813e1afd2..000000000 --- a/array/flatten.js +++ /dev/null @@ -1,32 +0,0 @@ -import baseFlatten from '../internal/baseFlatten'; -import isIterateeCall from '../internal/isIterateeCall'; - -/** - * Flattens a nested array. If `isDeep` is `true` the array is recursively - * flattened, otherwise it's only flattened a single level. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to flatten. - * @param {boolean} [isDeep] Specify a deep flatten. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {Array} Returns the new flattened array. - * @example - * - * _.flatten([1, [2, 3, [4]]]); - * // => [1, 2, 3, [4]] - * - * // using `isDeep` - * _.flatten([1, [2, 3, [4]]], true); - * // => [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) : []; -} - -export default flatten; diff --git a/array/head.js b/array/head.js deleted file mode 100644 index d29f16904..000000000 --- a/array/head.js +++ /dev/null @@ -1,2 +0,0 @@ -import first from './first' -export default first; diff --git a/array/intersection.js b/array/intersection.js deleted file mode 100644 index 9c883ecb0..000000000 --- a/array/intersection.js +++ /dev/null @@ -1,58 +0,0 @@ -import baseIndexOf from '../internal/baseIndexOf'; -import cacheIndexOf from '../internal/cacheIndexOf'; -import createCache from '../internal/createCache'; -import isArrayLike from '../internal/isArrayLike'; -import restParam from '../function/restParam'; - -/** - * Creates an array of unique values that are included in all of the provided - * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons. - * - * @static - * @memberOf _ - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of shared values. - * @example - * _.intersection([1, 2], [4, 2], [2, 1]); - * // => [2] - */ -var intersection = restParam(function(arrays) { - var othLength = arrays.length, - othIndex = othLength, - caches = Array(length), - indexOf = baseIndexOf, - isCommon = true, - result = []; - - while (othIndex--) { - var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; - caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null; - } - var array = arrays[0], - index = -1, - length = array ? array.length : 0, - seen = caches[0]; - - outer: - while (++index < length) { - value = array[index]; - if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { - var othIndex = othLength; - while (--othIndex) { - var cache = caches[othIndex]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { - continue outer; - } - } - if (seen) { - seen.push(value); - } - result.push(value); - } - } - return result; -}); - -export default intersection; diff --git a/array/object.js b/array/object.js deleted file mode 100644 index ac9db159c..000000000 --- a/array/object.js +++ /dev/null @@ -1,2 +0,0 @@ -import zipObject from './zipObject' -export default zipObject; diff --git a/array/pull.js b/array/pull.js deleted file mode 100644 index bbb8a1a11..000000000 --- a/array/pull.js +++ /dev/null @@ -1,52 +0,0 @@ -import baseIndexOf from '../internal/baseIndexOf'; - -/** Used for native method references. */ -var arrayProto = Array.prototype; - -/** Native method references. */ -var splice = arrayProto.splice; - -/** - * Removes all provided values from `array` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons. - * - * **Note:** Unlike `_.without`, this method mutates `array`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to modify. - * @param {...*} [values] The values to remove. - * @returns {Array} Returns `array`. - * @example - * - * var array = [1, 2, 3, 1, 2, 3]; - * - * _.pull(array, 2, 3); - * console.log(array); - * // => [1, 1] - */ -function pull() { - var args = arguments, - array = args[0]; - - if (!(array && array.length)) { - return array; - } - var index = 0, - indexOf = baseIndexOf, - length = args.length; - - while (++index < length) { - var fromIndex = 0, - value = args[index]; - - while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { - splice.call(array, fromIndex, 1); - } - } - return array; -} - -export default pull; diff --git a/array/pullAt.js b/array/pullAt.js deleted file mode 100644 index 92ee3553b..000000000 --- a/array/pullAt.js +++ /dev/null @@ -1,40 +0,0 @@ -import baseAt from '../internal/baseAt'; -import baseCompareAscending from '../internal/baseCompareAscending'; -import baseFlatten from '../internal/baseFlatten'; -import basePullAt from '../internal/basePullAt'; -import restParam from '../function/restParam'; - -/** - * Removes elements from `array` corresponding to the given indexes and returns - * an array of the removed elements. Indexes may be specified as an array of - * indexes or as individual arguments. - * - * **Note:** Unlike `_.at`, this method mutates `array`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to modify. - * @param {...(number|number[])} [indexes] The indexes of elements to remove, - * specified as individual indexes or arrays of indexes. - * @returns {Array} Returns the new array of removed elements. - * @example - * - * var array = [5, 10, 15, 20]; - * var evens = _.pullAt(array, 1, 3); - * - * console.log(array); - * // => [5, 15] - * - * console.log(evens); - * // => [10, 20] - */ -var pullAt = restParam(function(array, indexes) { - indexes = baseFlatten(indexes); - - var result = baseAt(array, indexes); - basePullAt(array, indexes.sort(baseCompareAscending)); - return result; -}); - -export default pullAt; diff --git a/array/sortedIndex.js b/array/sortedIndex.js deleted file mode 100644 index 720ed633e..000000000 --- a/array/sortedIndex.js +++ /dev/null @@ -1,53 +0,0 @@ -import createSortedIndex from '../internal/createSortedIndex'; - -/** - * Uses a binary search to determine the lowest index at which `value` should - * be inserted into `array` in order to maintain its sort order. If an iteratee - * function is provided it's invoked for `value` and each element of `array` - * to compute their sort ranking. The iteratee is bound to `thisArg` and - * invoked with one argument; (value). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - * @example - * - * _.sortedIndex([30, 50], 40); - * // => 1 - * - * _.sortedIndex([4, 4, 5, 5], 5); - * // => 2 - * - * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; - * - * // using an iteratee function - * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { - * return this.data[word]; - * }, dict); - * // => 1 - * - * // using the `_.property` callback shorthand - * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); - * // => 1 - */ -var sortedIndex = createSortedIndex(); - -export default sortedIndex; diff --git a/array/tail.js b/array/tail.js deleted file mode 100644 index 450e81b13..000000000 --- a/array/tail.js +++ /dev/null @@ -1,2 +0,0 @@ -import rest from './rest' -export default rest; diff --git a/array/takeRightWhile.js b/array/takeRightWhile.js deleted file mode 100644 index 1c29ef73e..000000000 --- a/array/takeRightWhile.js +++ /dev/null @@ -1,59 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import baseWhile from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.takeRightWhile([1, 2, 3], function(n) { - * return n > 1; - * }); - * // => [2, 3] - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': false } - * ]; - * - * // using the `_.matches` callback shorthand - * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user'); - * // => ['pebbles'] - * - * // using the `_.matchesProperty` callback shorthand - * _.pluck(_.takeRightWhile(users, 'active', false), 'user'); - * // => ['fred', 'pebbles'] - * - * // using the `_.property` callback shorthand - * _.pluck(_.takeRightWhile(users, 'active'), 'user'); - * // => [] - */ -function takeRightWhile(array, predicate, thisArg) { - return (array && array.length) - ? baseWhile(array, baseCallback(predicate, thisArg, 3), false, true) - : []; -} - -export default takeRightWhile; diff --git a/array/takeWhile.js b/array/takeWhile.js deleted file mode 100644 index f87169190..000000000 --- a/array/takeWhile.js +++ /dev/null @@ -1,59 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import baseWhile from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array to query. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.takeWhile([1, 2, 3], function(n) { - * return n < 3; - * }); - * // => [1, 2] - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false}, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * // using the `_.matches` callback shorthand - * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user'); - * // => ['barney'] - * - * // using the `_.matchesProperty` callback shorthand - * _.pluck(_.takeWhile(users, 'active', false), 'user'); - * // => ['barney', 'fred'] - * - * // using the `_.property` callback shorthand - * _.pluck(_.takeWhile(users, 'active'), 'user'); - * // => [] - */ -function takeWhile(array, predicate, thisArg) { - return (array && array.length) - ? baseWhile(array, baseCallback(predicate, thisArg, 3)) - : []; -} - -export default takeWhile; diff --git a/array/uniq.js b/array/uniq.js deleted file mode 100644 index 2975e023b..000000000 --- a/array/uniq.js +++ /dev/null @@ -1,71 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import baseUniq from '../internal/baseUniq'; -import isIterateeCall from '../internal/isIterateeCall'; -import sortedUniq from '../internal/sortedUniq'; - -/** - * Creates a duplicate-free version of an array, using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons, in which only the first occurence of each element - * is kept. Providing `true` for `isSorted` performs a faster search algorithm - * for sorted arrays. If an iteratee function is provided it's invoked for - * each element 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). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @alias unique - * @category Array - * @param {Array} array The array to inspect. - * @param {boolean} [isSorted] Specify the array is sorted. - * @param {Function|Object|string} [iteratee] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array} Returns the new duplicate-value-free array. - * @example - * - * _.uniq([2, 1, 2]); - * // => [2, 1] - * - * // using `isSorted` - * _.uniq([1, 1, 2], true); - * // => [1, 2] - * - * // using an iteratee function - * _.uniq([1, 2.5, 1.5, 2], function(n) { - * return this.floor(n); - * }, Math); - * // => [1, 2.5] - * - * // using the `_.property` callback shorthand - * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] - */ -function uniq(array, isSorted, iteratee, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - if (isSorted != null && typeof isSorted != 'boolean') { - thisArg = iteratee; - iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; - isSorted = false; - } - iteratee = iteratee == null ? iteratee : baseCallback(iteratee, thisArg, 3); - return (isSorted) - ? sortedUniq(array, iteratee) - : baseUniq(array, iteratee); -} - -export default uniq; diff --git a/array/unique.js b/array/unique.js deleted file mode 100644 index bca50d3cd..000000000 --- a/array/unique.js +++ /dev/null @@ -1,2 +0,0 @@ -import uniq from './uniq' -export default uniq; diff --git a/array/unzipWith.js b/array/unzipWith.js deleted file mode 100644 index 3c623a764..000000000 --- a/array/unzipWith.js +++ /dev/null @@ -1,41 +0,0 @@ -import arrayMap from '../internal/arrayMap'; -import arrayReduce from '../internal/arrayReduce'; -import bindCallback from '../internal/bindCallback'; -import unzip from './unzip'; - -/** - * This method is like `_.unzip` except that it accepts an iteratee to specify - * how regrouped values should be combined. The `iteratee` is bound to `thisArg` - * and invoked with four arguments: (accumulator, value, index, group). - * - * @static - * @memberOf _ - * @category Array - * @param {Array} array The array of grouped elements to process. - * @param {Function} [iteratee] The function to combine regrouped values. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array} Returns the new array of regrouped elements. - * @example - * - * var zipped = _.zip([1, 2], [10, 20], [100, 200]); - * // => [[1, 10, 100], [2, 20, 200]] - * - * _.unzipWith(zipped, _.add); - * // => [3, 30, 300] - */ -function unzipWith(array, iteratee, thisArg) { - var length = array ? array.length : 0; - if (!length) { - return []; - } - var result = unzip(array); - if (iteratee == null) { - return result; - } - iteratee = bindCallback(iteratee, thisArg, 4); - return arrayMap(result, function(group) { - return arrayReduce(group, iteratee, undefined, true); - }); -} - -export default unzipWith; diff --git a/array/xor.js b/array/xor.js deleted file mode 100644 index e1fdf86fe..000000000 --- a/array/xor.js +++ /dev/null @@ -1,35 +0,0 @@ -import arrayPush from '../internal/arrayPush'; -import baseDifference from '../internal/baseDifference'; -import baseUniq from '../internal/baseUniq'; -import isArrayLike from '../internal/isArrayLike'; - -/** - * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) - * of the provided arrays. - * - * @static - * @memberOf _ - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of values. - * @example - * - * _.xor([1, 2], [4, 2]); - * // => [1, 4] - */ -function xor() { - var index = -1, - length = arguments.length; - - while (++index < length) { - var array = arguments[index]; - if (isArrayLike(array)) { - var result = result - ? arrayPush(baseDifference(result, array), baseDifference(array, result)) - : array; - } - } - return result ? baseUniq(result) : []; -} - -export default xor; diff --git a/array/zipObject.js b/array/zipObject.js deleted file mode 100644 index 619d4984a..000000000 --- a/array/zipObject.js +++ /dev/null @@ -1,43 +0,0 @@ -import isArray from '../lang/isArray'; - -/** - * 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 _ - * @alias object - * @category Array - * @param {Array} props The property names. - * @param {Array} [values=[]] The property values. - * @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 } - */ -function zipObject(props, values) { - var index = -1, - length = props ? props.length : 0, - result = {}; - - if (length && !values && !isArray(props[0])) { - values = []; - } - while (++index < length) { - var key = props[index]; - if (values) { - result[key] = values[index]; - } else if (key) { - result[key[0]] = key[1]; - } - } - return result; -} - -export default zipObject; diff --git a/array/zipWith.js b/array/zipWith.js deleted file mode 100644 index 3823c7cca..000000000 --- a/array/zipWith.js +++ /dev/null @@ -1,36 +0,0 @@ -import restParam from '../function/restParam'; -import unzipWith from './unzipWith'; - -/** - * This method is like `_.zip` except that it accepts an iteratee to specify - * how grouped values should be combined. The `iteratee` is bound to `thisArg` - * and invoked with four arguments: (accumulator, value, index, group). - * - * @static - * @memberOf _ - * @category Array - * @param {...Array} [arrays] The arrays to process. - * @param {Function} [iteratee] The function to combine grouped values. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array} Returns the new array of grouped elements. - * @example - * - * _.zipWith([1, 2], [10, 20], [100, 200], _.add); - * // => [111, 222] - */ -var zipWith = restParam(function(arrays) { - var length = arrays.length, - iteratee = length > 2 ? arrays[length - 2] : undefined, - thisArg = length > 1 ? arrays[length - 1] : undefined; - - if (length > 2 && typeof iteratee == 'function') { - length -= 2; - } else { - iteratee = (length > 1 && typeof thisArg == 'function') ? (--length, thisArg) : undefined; - thisArg = undefined; - } - arrays.length = length; - return unzipWith(arrays, iteratee, thisArg); -}); - -export default zipWith; diff --git a/function/ary.js b/ary.js similarity index 51% rename from function/ary.js rename to ary.js index f0f7ef209..092d31797 100644 --- a/function/ary.js +++ b/ary.js @@ -1,14 +1,10 @@ -import createWrapper from '../internal/createWrapper'; -import isIterateeCall from '../internal/isIterateeCall'; +import createWrapper from './internal/createWrapper'; /** Used to compose bitmasks for wrapper metadata. */ var ARY_FLAG = 128; -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; - /** - * Creates a function that accepts up to `n` arguments ignoring any + * Creates a function that accepts up to `n` arguments, ignoring any * additional arguments. * * @static @@ -16,7 +12,7 @@ var nativeMax = Math.max; * @category Function * @param {Function} func The function to cap arguments for. * @param {number} [n=func.length] The arity cap. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Function} Returns the new function. * @example * @@ -24,10 +20,8 @@ var nativeMax = Math.max; * // => [6, 8, 10] */ function ary(func, n, guard) { - if (guard && isIterateeCall(func, n, guard)) { - n = undefined; - } - n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); } diff --git a/assign.js b/assign.js new file mode 100644 index 000000000..6d7af5ede --- /dev/null +++ b/assign.js @@ -0,0 +1,39 @@ +import copyObject from './internal/copyObject'; +import createAssigner from './internal/createAssigner'; +import keys from './keys'; + +/** + * Assigns own enumerable properties of source objects to the destination + * object. Source objects are applied from left to right. Subsequent sources + * overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * function Foo() { + * this.c = 3; + * } + * + * function Bar() { + * this.e = 5; + * } + * + * Foo.prototype.d = 4; + * Bar.prototype.f = 6; + * + * _.assign({ 'a': 1 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3, 'e': 5 } + */ +var assign = createAssigner(function(object, source) { + copyObject(source, keys(source), object); +}); + +export default assign; diff --git a/assignIn.js b/assignIn.js new file mode 100644 index 000000000..a0ead9eda --- /dev/null +++ b/assignIn.js @@ -0,0 +1,38 @@ +import copyObject from './internal/copyObject'; +import createAssigner from './internal/createAssigner'; +import keysIn from './keysIn'; + +/** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * function Bar() { + * this.d = 4; + * } + * + * Foo.prototype.c = 3; + * Bar.prototype.e = 5; + * + * _.assignIn({ 'a': 1 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 } + */ +var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); +}); + +export default assignIn; diff --git a/assignInWith.js b/assignInWith.js new file mode 100644 index 000000000..b477a655c --- /dev/null +++ b/assignInWith.js @@ -0,0 +1,36 @@ +import copyObjectWith from './internal/copyObjectWith'; +import createAssigner from './internal/createAssigner'; +import keysIn from './keysIn'; + +/** + * This method is like `_.assignIn` except that it accepts `customizer` which + * is invoked to produce the assigned values. If `customizer` returns `undefined` + * assignment is handled by the method instead. The `customizer` is invoked + * with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var assignInWith = createAssigner(function(object, source, customizer) { + copyObjectWith(source, keysIn(source), object, customizer); +}); + +export default assignInWith; diff --git a/assignWith.js b/assignWith.js new file mode 100644 index 000000000..410a641c7 --- /dev/null +++ b/assignWith.js @@ -0,0 +1,35 @@ +import copyObjectWith from './internal/copyObjectWith'; +import createAssigner from './internal/createAssigner'; +import keys from './keys'; + +/** + * This method is like `_.assign` except that it accepts `customizer` which + * is invoked to produce the assigned values. If `customizer` returns `undefined` + * assignment is handled by the method instead. The `customizer` is invoked + * with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var assignWith = createAssigner(function(object, source, customizer) { + copyObjectWith(source, keys(source), object, customizer); +}); + +export default assignWith; diff --git a/at.js b/at.js new file mode 100644 index 000000000..686d950d7 --- /dev/null +++ b/at.js @@ -0,0 +1,29 @@ +import baseAt from './internal/baseAt'; +import baseFlatten from './internal/baseFlatten'; +import rest from './rest'; + +/** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths of elements to pick, + * specified individually or in arrays. + * @returns {Array} Returns the new array of picked elements. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + * + * _.at(['a', 'b', 'c'], 0, 2); + * // => ['a', 'c'] + */ +var at = rest(function(object, paths) { + return baseAt(object, baseFlatten(paths)); +}); + +export default at; diff --git a/utility/attempt.js b/attempt.js similarity index 74% rename from utility/attempt.js rename to attempt.js index 022dc5675..4ff7bd591 100644 --- a/utility/attempt.js +++ b/attempt.js @@ -1,5 +1,6 @@ -import isError from '../lang/isError'; -import restParam from '../function/restParam'; +import apply from './internal/apply'; +import isError from './isError'; +import rest from './rest'; /** * Attempts to invoke `func`, returning either the result or the caught error @@ -7,7 +8,7 @@ import restParam from '../function/restParam'; * * @static * @memberOf _ - * @category Utility + * @category Util * @param {Function} func The function to attempt. * @returns {*} Returns the `func` result or error object. * @example @@ -21,10 +22,10 @@ import restParam from '../function/restParam'; * elements = []; * } */ -var attempt = restParam(function(func, args) { +var attempt = rest(function(func, args) { try { - return func.apply(undefined, args); - } catch(e) { + return apply(func, undefined, args); + } catch (e) { return isError(e) ? e : new Error(e); } }); diff --git a/function/before.js b/before.js similarity index 81% rename from function/before.js rename to before.js index cc830d056..39ace0f53 100644 --- a/function/before.js +++ b/before.js @@ -1,3 +1,5 @@ +import toInteger from './toInteger'; + /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -14,20 +16,15 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * @returns {Function} Returns the new restricted function. * @example * - * jQuery('#add').on('click', _.before(5, addContactToList)); + * jQuery(element).on('click', _.before(5, addContactToList)); * // => allows adding up to 4 contacts to the list */ function before(n, func) { var result; if (typeof func != 'function') { - if (typeof n == 'function') { - var temp = n; - n = func; - func = temp; - } else { - throw new TypeError(FUNC_ERROR_TEXT); - } + throw new TypeError(FUNC_ERROR_TEXT); } + n = toInteger(n); return function() { if (--n > 0) { result = func.apply(this, arguments); diff --git a/function/bind.js b/bind.js similarity index 79% rename from function/bind.js rename to bind.js index fe0adb9e8..157a8ec74 100644 --- a/function/bind.js +++ b/bind.js @@ -1,6 +1,6 @@ -import createWrapper from '../internal/createWrapper'; -import replaceHolders from '../internal/replaceHolders'; -import restParam from './restParam'; +import createWrapper from './internal/createWrapper'; +import replaceHolders from './internal/replaceHolders'; +import rest from './rest'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -14,7 +14,7 @@ var BIND_FLAG = 1, * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for partially applied arguments. * - * **Note:** Unlike native `Function#bind` this method does not set the "length" + * **Note:** Unlike native `Function#bind` this method doesn't set the "length" * property of bound functions. * * @static @@ -41,7 +41,7 @@ var BIND_FLAG = 1, * bound('hi'); * // => 'hi fred!' */ -var bind = restParam(function(func, thisArg, partials) { +var bind = rest(function(func, thisArg, partials) { var bitmask = BIND_FLAG; if (partials.length) { var holders = replaceHolders(partials, bind.placeholder); @@ -50,7 +50,4 @@ var bind = restParam(function(func, thisArg, partials) { return createWrapper(func, bitmask, thisArg, partials, holders); }); -// Assign default placeholders. -bind.placeholder = {}; - export default bind; diff --git a/bindAll.js b/bindAll.js new file mode 100644 index 000000000..eb5229dc3 --- /dev/null +++ b/bindAll.js @@ -0,0 +1,39 @@ +import arrayEach from './internal/arrayEach'; +import baseFlatten from './internal/baseFlatten'; +import bind from './bind'; +import rest from './rest'; + +/** + * Binds methods of an object to the object itself, overwriting the existing + * method. + * + * **Note:** This method doesn't set the "length" property of bound functions. + * + * @static + * @memberOf _ + * @category Util + * @param {Object} object The object to bind and assign the bound methods to. + * @param {...(string|string[])} methodNames The object method names to bind, + * specified individually or in arrays. + * @returns {Object} Returns `object`. + * @example + * + * var view = { + * 'label': 'docs', + * 'onClick': function() { + * console.log('clicked ' + this.label); + * } + * }; + * + * _.bindAll(view, 'onClick'); + * jQuery(element).on('click', view.onClick); + * // => logs 'clicked docs' when clicked + */ +var bindAll = rest(function(object, methodNames) { + arrayEach(baseFlatten(methodNames), function(key) { + object[key] = bind(object[key], object); + }); + return object; +}); + +export default bindAll; diff --git a/function/bindKey.js b/bindKey.js similarity index 83% rename from function/bindKey.js rename to bindKey.js index 20c6a4441..3af317bf5 100644 --- a/function/bindKey.js +++ b/bindKey.js @@ -1,6 +1,6 @@ -import createWrapper from '../internal/createWrapper'; -import replaceHolders from '../internal/replaceHolders'; -import restParam from './restParam'; +import createWrapper from './internal/createWrapper'; +import replaceHolders from './internal/replaceHolders'; +import rest from './rest'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -22,7 +22,7 @@ var BIND_FLAG = 1, * @static * @memberOf _ * @category Function - * @param {Object} object The object the method belongs to. + * @param {Object} object The object to invoke the method on. * @param {string} key The key of the method. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. @@ -51,7 +51,7 @@ var BIND_FLAG = 1, * bound('hi'); * // => 'hiya fred!' */ -var bindKey = restParam(function(object, key, partials) { +var bindKey = rest(function(object, key, partials) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (partials.length) { var holders = replaceHolders(partials, bindKey.placeholder); @@ -60,7 +60,4 @@ var bindKey = restParam(function(object, key, partials) { return createWrapper(key, bitmask, object, partials, holders); }); -// Assign default placeholders. -bindKey.placeholder = {}; - export default bindKey; diff --git a/string/camelCase.js b/camelCase.js similarity index 77% rename from string/camelCase.js rename to camelCase.js index e1ff211dc..ca3c15f0d 100644 --- a/string/camelCase.js +++ b/camelCase.js @@ -1,4 +1,5 @@ -import createCompounder from '../internal/createCompounder'; +import capitalize from './capitalize'; +import createCompounder from './internal/createCompounder'; /** * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). @@ -21,7 +22,7 @@ import createCompounder from '../internal/createCompounder'; */ var camelCase = createCompounder(function(result, word, index) { word = word.toLowerCase(); - return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word); + return result + (index ? capitalize(word) : word); }); export default camelCase; diff --git a/string/capitalize.js b/capitalize.js similarity index 51% rename from string/capitalize.js rename to capitalize.js index 307f66324..828dcc6da 100644 --- a/string/capitalize.js +++ b/capitalize.js @@ -1,7 +1,9 @@ -import baseToString from '../internal/baseToString'; +import toString from './toString'; +import upperFirst from './upperFirst'; /** - * Capitalizes the first character of `string`. + * Converts the first character of `string` to upper case and the remaining + * to lower case. * * @static * @memberOf _ @@ -10,12 +12,11 @@ import baseToString from '../internal/baseToString'; * @returns {string} Returns the capitalized string. * @example * - * _.capitalize('fred'); + * _.capitalize('FRED'); * // => 'Fred' */ function capitalize(string) { - string = baseToString(string); - return string && (string.charAt(0).toUpperCase() + string.slice(1)); + return upperFirst(toString(string).toLowerCase()); } export default capitalize; diff --git a/math/ceil.js b/ceil.js similarity index 69% rename from math/ceil.js rename to ceil.js index 7ffa2b423..8a0ff4afd 100644 --- a/math/ceil.js +++ b/ceil.js @@ -1,12 +1,12 @@ -import createRound from '../internal/createRound'; +import createRound from './internal/createRound'; /** - * Calculates `n` rounded up to `precision`. + * Computes `number` rounded up to `precision`. * * @static * @memberOf _ * @category Math - * @param {number} n The number to round up. + * @param {number} number The number to round up. * @param {number} [precision=0] The precision to round up to. * @returns {number} Returns the rounded up number. * @example diff --git a/chain.js b/chain.js index e029e2b8f..7d4ae2de6 100644 --- a/chain.js +++ b/chain.js @@ -1,31 +1,36 @@ -import chain from './chain/chain'; -import commit from './chain/commit'; -import concat from './chain/concat'; -import lodash from './chain/lodash'; -import plant from './chain/plant'; -import reverse from './chain/reverse'; -import run from './chain/run'; -import tap from './chain/tap'; -import thru from './chain/thru'; -import toJSON from './chain/toJSON'; -import toString from './chain/toString'; -import value from './chain/value'; -import valueOf from './chain/valueOf'; -import wrapperChain from './chain/wrapperChain'; +import lodash from './wrapperLodash'; -export default { - 'chain': chain, - 'commit': commit, - 'concat': concat, - 'lodash': lodash, - 'plant': plant, - 'reverse': reverse, - 'run': run, - 'tap': tap, - 'thru': thru, - 'toJSON': toJSON, - 'toString': toString, - 'value': value, - 'valueOf': valueOf, - 'wrapperChain': wrapperChain -}; +/** + * Creates a `lodash` object that wraps `value` with explicit method chaining enabled. + * The result of such method chaining must be unwrapped with `_#value`. + * + * @static + * @memberOf _ + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ +function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; +} + +export default chain; diff --git a/chain/chain.js b/chain/chain.js deleted file mode 100644 index 03b9999c9..000000000 --- a/chain/chain.js +++ /dev/null @@ -1,35 +0,0 @@ -import lodash from './lodash'; - -/** - * Creates a `lodash` object that wraps `value` with explicit method - * chaining enabled. - * - * @static - * @memberOf _ - * @category Chain - * @param {*} value The value to wrap. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 }, - * { 'user': 'pebbles', 'age': 1 } - * ]; - * - * var youngest = _.chain(users) - * .sortBy('age') - * .map(function(chr) { - * return chr.user + ' is ' + chr.age; - * }) - * .first() - * .value(); - * // => 'pebbles is 1' - */ -function chain(value) { - var result = lodash(value); - result.__chain__ = true; - return result; -} - -export default chain; diff --git a/chain/commit.js b/chain/commit.js deleted file mode 100644 index 3a1110c5a..000000000 --- a/chain/commit.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperCommit from './wrapperCommit' -export default wrapperCommit; diff --git a/chain/concat.js b/chain/concat.js deleted file mode 100644 index 2fabc0707..000000000 --- a/chain/concat.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperConcat from './wrapperConcat' -export default wrapperConcat; diff --git a/chain/lodash.js b/chain/lodash.js deleted file mode 100644 index 958e64f85..000000000 --- a/chain/lodash.js +++ /dev/null @@ -1,125 +0,0 @@ -import LazyWrapper from '../internal/LazyWrapper'; -import LodashWrapper from '../internal/LodashWrapper'; -import baseLodash from '../internal/baseLodash'; -import isArray from '../lang/isArray'; -import isObjectLike from '../internal/isObjectLike'; -import wrapperClone from '../internal/wrapperClone'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Creates a `lodash` object which wraps `value` to enable implicit chaining. - * Methods that operate on and return arrays, collections, and functions can - * be chained together. Methods that retrieve a single value or may return a - * primitive value will automatically end the chain returning the unwrapped - * value. Explicit chaining may be enabled using `_.chain`. The execution of - * chained methods is lazy, that is, execution is deferred until `_#value` - * is implicitly or explicitly called. - * - * Lazy evaluation allows several methods to support shortcut fusion. Shortcut - * fusion is an optimization strategy which merge iteratee calls; this can help - * to avoid the creation of intermediate data structures and greatly reduce the - * number of iteratee executions. - * - * Chaining is supported in custom builds as long as the `_#value` method is - * directly or indirectly included in the build. - * - * In addition to lodash methods, wrappers have `Array` and `String` methods. - * - * The wrapper `Array` methods are: - * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, - * `splice`, and `unshift` - * - * The wrapper `String` methods are: - * `replace` and `split` - * - * The wrapper methods that support shortcut fusion are: - * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, - * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, - * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`, - * and `where` - * - * The chainable wrapper methods are: - * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, - * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, - * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, - * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, - * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, - * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, - * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, - * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, - * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, - * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, - * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, - * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, - * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, - * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, - * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, - * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, - * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` - * - * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, - * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, - * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, - * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, - * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, - * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, - * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, - * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, - * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, - * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, - * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, - * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, - * `unescape`, `uniqueId`, `value`, and `words` - * - * The wrapper method `sample` will return a wrapped value when `n` is provided, - * otherwise an unwrapped value is returned. - * - * @name _ - * @constructor - * @category Chain - * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var wrapped = _([1, 2, 3]); - * - * // returns an unwrapped value - * wrapped.reduce(function(total, n) { - * return total + n; - * }); - * // => 6 - * - * // returns a wrapped value - * var squares = wrapped.map(function(n) { - * return n * n; - * }); - * - * _.isArray(squares); - * // => false - * - * _.isArray(squares.value()); - * // => true - */ -function lodash(value) { - if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { - if (value instanceof LodashWrapper) { - return value; - } - if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) { - return wrapperClone(value); - } - } - return new LodashWrapper(value); -} - -// Ensure wrappers are instances of `baseLodash`. -lodash.prototype = baseLodash.prototype; - -export default lodash; diff --git a/chain/plant.js b/chain/plant.js deleted file mode 100644 index 6ccd45ee5..000000000 --- a/chain/plant.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperPlant from './wrapperPlant' -export default wrapperPlant; diff --git a/chain/reverse.js b/chain/reverse.js deleted file mode 100644 index 5602fa286..000000000 --- a/chain/reverse.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperReverse from './wrapperReverse' -export default wrapperReverse; diff --git a/chain/run.js b/chain/run.js deleted file mode 100644 index 59ae6ce2a..000000000 --- a/chain/run.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperValue from './wrapperValue' -export default wrapperValue; diff --git a/chain/toJSON.js b/chain/toJSON.js deleted file mode 100644 index 59ae6ce2a..000000000 --- a/chain/toJSON.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperValue from './wrapperValue' -export default wrapperValue; diff --git a/chain/toString.js b/chain/toString.js deleted file mode 100644 index 2600cac23..000000000 --- a/chain/toString.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperToString from './wrapperToString' -export default wrapperToString; diff --git a/chain/value.js b/chain/value.js deleted file mode 100644 index 59ae6ce2a..000000000 --- a/chain/value.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperValue from './wrapperValue' -export default wrapperValue; diff --git a/chain/valueOf.js b/chain/valueOf.js deleted file mode 100644 index 59ae6ce2a..000000000 --- a/chain/valueOf.js +++ /dev/null @@ -1,2 +0,0 @@ -import wrapperValue from './wrapperValue' -export default wrapperValue; diff --git a/chain/wrapperConcat.js b/chain/wrapperConcat.js deleted file mode 100644 index 944e2c96f..000000000 --- a/chain/wrapperConcat.js +++ /dev/null @@ -1,34 +0,0 @@ -import arrayConcat from '../internal/arrayConcat'; -import baseFlatten from '../internal/baseFlatten'; -import isArray from '../lang/isArray'; -import restParam from '../function/restParam'; -import toObject from '../internal/toObject'; - -/** - * Creates a new array joining a wrapped array with any additional arrays - * and/or values. - * - * @name concat - * @memberOf _ - * @category Chain - * @param {...*} [values] The values to concatenate. - * @returns {Array} Returns the new concatenated array. - * @example - * - * var array = [1]; - * var wrapped = _(array).concat(2, [3], [[4]]); - * - * console.log(wrapped.value()); - * // => [1, 2, 3, [4]] - * - * console.log(array); - * // => [1] - */ -var wrapperConcat = restParam(function(values) { - values = baseFlatten(values); - return this.thru(function(array) { - return arrayConcat(isArray(array) ? array : [toObject(array)], values); - }); -}); - -export default wrapperConcat; diff --git a/chain/wrapperToString.js b/chain/wrapperToString.js deleted file mode 100644 index 21f6db4a5..000000000 --- a/chain/wrapperToString.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Produces the result of coercing the unwrapped value to a string. - * - * @name toString - * @memberOf _ - * @category Chain - * @returns {string} Returns the coerced string value. - * @example - * - * _([1, 2, 3]).toString(); - * // => '1,2,3' - */ -function wrapperToString() { - return (this.value() + ''); -} - -export default wrapperToString; diff --git a/array/chunk.js b/chunk.js similarity index 51% rename from array/chunk.js rename to chunk.js index 3bde8716f..698ddc165 100644 --- a/array/chunk.js +++ b/chunk.js @@ -1,22 +1,20 @@ -import baseSlice from '../internal/baseSlice'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseSlice from './internal/baseSlice'; +import toInteger from './toInteger'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil, - nativeFloor = Math.floor, nativeMax = Math.max; /** * Creates an array of elements split into groups the length of `size`. - * If `collection` can't be split evenly, the final chunk will be the remaining + * If `array` can't be split evenly, the final chunk will be the remaining * elements. * * @static * @memberOf _ * @category Array * @param {Array} array The array to process. - * @param {number} [size=1] The length of each chunk. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param {number} [size=0] The length of each chunk. * @returns {Array} Returns the new array containing chunks. * @example * @@ -26,14 +24,14 @@ var nativeCeil = Math.ceil, * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ -function chunk(array, size, guard) { - if (guard ? isIterateeCall(array, size, guard) : size == null) { - size = 1; - } else { - size = nativeMax(nativeFloor(size) || 1, 1); +function chunk(array, size) { + size = nativeMax(toInteger(size), 0); + + var length = array ? array.length : 0; + if (!length || size < 1) { + return []; } var index = 0, - length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); diff --git a/clamp.js b/clamp.js new file mode 100644 index 000000000..59c63d30e --- /dev/null +++ b/clamp.js @@ -0,0 +1,38 @@ +import baseClamp from './internal/baseClamp'; +import toNumber from './toNumber'; + +/** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ +function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); +} + +export default clamp; diff --git a/clone.js b/clone.js new file mode 100644 index 000000000..4bbda5540 --- /dev/null +++ b/clone.js @@ -0,0 +1,31 @@ +import baseClone from './internal/baseClone'; + +/** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ +function clone(value) { + return baseClone(value); +} + +export default clone; diff --git a/cloneDeep.js b/cloneDeep.js new file mode 100644 index 000000000..7bfd3eb48 --- /dev/null +++ b/cloneDeep.js @@ -0,0 +1,23 @@ +import baseClone from './internal/baseClone'; + +/** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ +function cloneDeep(value) { + return baseClone(value, true); +} + +export default cloneDeep; diff --git a/cloneDeepWith.js b/cloneDeepWith.js new file mode 100644 index 000000000..dce45adf1 --- /dev/null +++ b/cloneDeepWith.js @@ -0,0 +1,33 @@ +import baseClone from './internal/baseClone'; + +/** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeep(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ +function cloneDeepWith(value, customizer) { + return baseClone(value, true, customizer); +} + +export default cloneDeepWith; diff --git a/cloneWith.js b/cloneWith.js new file mode 100644 index 000000000..628579923 --- /dev/null +++ b/cloneWith.js @@ -0,0 +1,36 @@ +import baseClone from './internal/baseClone'; + +/** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined` + * cloning is handled by the method instead. The `customizer` is invoked with + * up to five arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.clone(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ +function cloneWith(value, customizer) { + return baseClone(value, false, customizer); +} + +export default cloneWith; diff --git a/collection.default.js b/collection.default.js new file mode 100644 index 000000000..6b5cec830 --- /dev/null +++ b/collection.default.js @@ -0,0 +1,35 @@ +import at from './at'; +import countBy from './countBy'; +import each from './each'; +import eachRight from './eachRight'; +import every from './every'; +import filter from './filter'; +import find from './find'; +import findLast from './findLast'; +import forEach from './forEach'; +import forEachRight from './forEachRight'; +import groupBy from './groupBy'; +import includes from './includes'; +import invokeMap from './invokeMap'; +import keyBy from './keyBy'; +import map from './map'; +import orderBy from './orderBy'; +import partition from './partition'; +import reduce from './reduce'; +import reduceRight from './reduceRight'; +import reject from './reject'; +import sample from './sample'; +import sampleSize from './sampleSize'; +import shuffle from './shuffle'; +import size from './size'; +import some from './some'; +import sortBy from './sortBy'; + +export default { + at, countBy, each, eachRight, every, + filter, find, findLast, forEach, forEachRight, + groupBy, includes, invokeMap, keyBy, map, + orderBy, partition, reduce, reduceRight, reject, + sample, sampleSize, shuffle, size, some, + sortBy +}; diff --git a/collection.js b/collection.js index d1a94a5cb..8dad26274 100644 --- a/collection.js +++ b/collection.js @@ -1,87 +1,27 @@ -import all from './collection/all'; -import any from './collection/any'; -import at from './collection/at'; -import collect from './collection/collect'; -import contains from './collection/contains'; -import countBy from './collection/countBy'; -import detect from './collection/detect'; -import each from './collection/each'; -import eachRight from './collection/eachRight'; -import every from './collection/every'; -import filter from './collection/filter'; -import find from './collection/find'; -import findLast from './collection/findLast'; -import findWhere from './collection/findWhere'; -import foldl from './collection/foldl'; -import foldr from './collection/foldr'; -import forEach from './collection/forEach'; -import forEachRight from './collection/forEachRight'; -import groupBy from './collection/groupBy'; -import include from './collection/include'; -import includes from './collection/includes'; -import indexBy from './collection/indexBy'; -import inject from './collection/inject'; -import invoke from './collection/invoke'; -import map from './collection/map'; -import max from './math/max'; -import min from './math/min'; -import partition from './collection/partition'; -import pluck from './collection/pluck'; -import reduce from './collection/reduce'; -import reduceRight from './collection/reduceRight'; -import reject from './collection/reject'; -import sample from './collection/sample'; -import select from './collection/select'; -import shuffle from './collection/shuffle'; -import size from './collection/size'; -import some from './collection/some'; -import sortBy from './collection/sortBy'; -import sortByAll from './collection/sortByAll'; -import sortByOrder from './collection/sortByOrder'; -import sum from './math/sum'; -import where from './collection/where'; - -export default { - 'all': all, - 'any': any, - 'at': at, - 'collect': collect, - 'contains': contains, - 'countBy': countBy, - 'detect': detect, - 'each': each, - 'eachRight': eachRight, - 'every': every, - 'filter': filter, - 'find': find, - 'findLast': findLast, - 'findWhere': findWhere, - 'foldl': foldl, - 'foldr': foldr, - 'forEach': forEach, - 'forEachRight': forEachRight, - 'groupBy': groupBy, - 'include': include, - 'includes': includes, - 'indexBy': indexBy, - 'inject': inject, - 'invoke': invoke, - 'map': map, - 'max': max, - 'min': min, - 'partition': partition, - 'pluck': pluck, - 'reduce': reduce, - 'reduceRight': reduceRight, - 'reject': reject, - 'sample': sample, - 'select': select, - 'shuffle': shuffle, - 'size': size, - 'some': some, - 'sortBy': sortBy, - 'sortByAll': sortByAll, - 'sortByOrder': sortByOrder, - 'sum': sum, - 'where': where -}; +export { default as at } from './at'; +export { default as countBy } from './countBy'; +export { default as each } from './each'; +export { default as eachRight } from './eachRight'; +export { default as every } from './every'; +export { default as filter } from './filter'; +export { default as find } from './find'; +export { default as findLast } from './findLast'; +export { default as forEach } from './forEach'; +export { default as forEachRight } from './forEachRight'; +export { default as groupBy } from './groupBy'; +export { default as includes } from './includes'; +export { default as invokeMap } from './invokeMap'; +export { default as keyBy } from './keyBy'; +export { default as map } from './map'; +export { default as orderBy } from './orderBy'; +export { default as partition } from './partition'; +export { default as reduce } from './reduce'; +export { default as reduceRight } from './reduceRight'; +export { default as reject } from './reject'; +export { default as sample } from './sample'; +export { default as sampleSize } from './sampleSize'; +export { default as shuffle } from './shuffle'; +export { default as size } from './size'; +export { default as some } from './some'; +export { default as sortBy } from './sortBy'; +export { default as default } from './collection.default'; diff --git a/collection/all.js b/collection/all.js deleted file mode 100644 index 723b5f8e5..000000000 --- a/collection/all.js +++ /dev/null @@ -1,2 +0,0 @@ -import every from './every' -export default every; diff --git a/collection/any.js b/collection/any.js deleted file mode 100644 index 2da88029b..000000000 --- a/collection/any.js +++ /dev/null @@ -1,2 +0,0 @@ -import some from './some' -export default some; diff --git a/collection/at.js b/collection/at.js deleted file mode 100644 index a0135c59e..000000000 --- a/collection/at.js +++ /dev/null @@ -1,29 +0,0 @@ -import baseAt from '../internal/baseAt'; -import baseFlatten from '../internal/baseFlatten'; -import restParam from '../function/restParam'; - -/** - * Creates an array of elements corresponding to the given keys, or indexes, - * of `collection`. Keys may be specified as individual arguments or as arrays - * of keys. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [props] The property names - * or indexes of elements to pick, specified individually or in arrays. - * @returns {Array} Returns the new array of picked elements. - * @example - * - * _.at(['a', 'b', 'c'], [0, 2]); - * // => ['a', 'c'] - * - * _.at(['barney', 'fred', 'pebbles'], 0, 2); - * // => ['barney', 'pebbles'] - */ -var at = restParam(function(collection, props) { - return baseAt(collection, baseFlatten(props)); -}); - -export default at; diff --git a/collection/collect.js b/collection/collect.js deleted file mode 100644 index 982f50a4c..000000000 --- a/collection/collect.js +++ /dev/null @@ -1,2 +0,0 @@ -import map from './map' -export default map; diff --git a/collection/contains.js b/collection/contains.js deleted file mode 100644 index a1520e467..000000000 --- a/collection/contains.js +++ /dev/null @@ -1,2 +0,0 @@ -import includes from './includes' -export default includes; diff --git a/collection/countBy.js b/collection/countBy.js deleted file mode 100644 index 3f5253a5c..000000000 --- a/collection/countBy.js +++ /dev/null @@ -1,54 +0,0 @@ -import createAggregator from '../internal/createAggregator'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -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: - * (value, index|key, collection). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * _.countBy([4.3, 6.1, 6.4], function(n) { - * return Math.floor(n); - * }); - * // => { '4': 1, '6': 2 } - * - * _.countBy([4.3, 6.1, 6.4], function(n) { - * return this.floor(n); - * }, Math); - * // => { '4': 1, '6': 2 } - * - * _.countBy(['one', 'two', 'three'], 'length'); - * // => { '3': 2, '5': 1 } - */ -var countBy = createAggregator(function(result, value, key) { - hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); -}); - -export default countBy; diff --git a/collection/detect.js b/collection/detect.js deleted file mode 100644 index 3496fdc3e..000000000 --- a/collection/detect.js +++ /dev/null @@ -1,2 +0,0 @@ -import find from './find' -export default find; diff --git a/collection/each.js b/collection/each.js deleted file mode 100644 index 182b7b709..000000000 --- a/collection/each.js +++ /dev/null @@ -1,2 +0,0 @@ -import forEach from './forEach' -export default forEach; diff --git a/collection/eachRight.js b/collection/eachRight.js deleted file mode 100644 index 24047ca09..000000000 --- a/collection/eachRight.js +++ /dev/null @@ -1,2 +0,0 @@ -import forEachRight from './forEachRight' -export default forEachRight; diff --git a/collection/every.js b/collection/every.js deleted file mode 100644 index 9d48de9af..000000000 --- a/collection/every.js +++ /dev/null @@ -1,66 +0,0 @@ -import arrayEvery from '../internal/arrayEvery'; -import baseCallback from '../internal/baseCallback'; -import baseEvery from '../internal/baseEvery'; -import isArray from '../lang/isArray'; -import isIterateeCall from '../internal/isIterateeCall'; - -/** - * Checks if `predicate` returns truthy for **all** elements of `collection`. - * 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` - * 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @alias all - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {boolean} Returns `true` if all elements pass the predicate check, - * else `false`. - * @example - * - * _.every([true, 1, null, 'yes'], Boolean); - * // => false - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false } - * ]; - * - * // using the `_.matches` callback shorthand - * _.every(users, { 'user': 'barney', 'active': false }); - * // => false - * - * // using the `_.matchesProperty` callback shorthand - * _.every(users, 'active', false); - * // => true - * - * // using the `_.property` callback shorthand - * _.every(users, 'active'); - * // => false - */ -function every(collection, predicate, thisArg) { - var func = isArray(collection) ? arrayEvery : baseEvery; - if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = undefined; - } - if (typeof predicate != 'function' || thisArg !== undefined) { - predicate = baseCallback(predicate, thisArg, 3); - } - return func(collection, predicate); -} - -export default every; diff --git a/collection/filter.js b/collection/filter.js deleted file mode 100644 index 2d90dbb1c..000000000 --- a/collection/filter.js +++ /dev/null @@ -1,61 +0,0 @@ -import arrayFilter from '../internal/arrayFilter'; -import baseCallback from '../internal/baseCallback'; -import baseFilter from '../internal/baseFilter'; -import isArray from '../lang/isArray'; - -/** - * 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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @alias select - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the new filtered array. - * @example - * - * _.filter([4, 5, 6], function(n) { - * return n % 2 == 0; - * }); - * // => [4, 6] - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false } - * ]; - * - * // using the `_.matches` callback shorthand - * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user'); - * // => ['barney'] - * - * // using the `_.matchesProperty` callback shorthand - * _.pluck(_.filter(users, 'active', false), 'user'); - * // => ['fred'] - * - * // using the `_.property` callback shorthand - * _.pluck(_.filter(users, 'active'), 'user'); - * // => ['barney'] - */ -function filter(collection, predicate, thisArg) { - var func = isArray(collection) ? arrayFilter : baseFilter; - predicate = baseCallback(predicate, thisArg, 3); - return func(collection, predicate); -} - -export default filter; diff --git a/collection/find.js b/collection/find.js deleted file mode 100644 index 66df162e7..000000000 --- a/collection/find.js +++ /dev/null @@ -1,56 +0,0 @@ -import baseEach from '../internal/baseEach'; -import createFind from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @alias detect - * @category Collection - * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false }, - * { 'user': 'pebbles', 'age': 1, 'active': true } - * ]; - * - * _.result(_.find(users, function(chr) { - * return chr.age < 40; - * }), 'user'); - * // => 'barney' - * - * // using the `_.matches` callback shorthand - * _.result(_.find(users, { 'age': 1, 'active': true }), 'user'); - * // => 'pebbles' - * - * // using the `_.matchesProperty` callback shorthand - * _.result(_.find(users, 'active', false), 'user'); - * // => 'fred' - * - * // using the `_.property` callback shorthand - * _.result(_.find(users, 'active'), 'user'); - * // => 'barney' - */ -var find = createFind(baseEach); - -export default find; diff --git a/collection/findLast.js b/collection/findLast.js deleted file mode 100644 index 1fc980e71..000000000 --- a/collection/findLast.js +++ /dev/null @@ -1,25 +0,0 @@ -import baseEachRight from '../internal/baseEachRight'; -import createFind from '../internal/createFind'; - -/** - * This method is like `_.find` except that it iterates over elements of - * `collection` from right to left. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * _.findLast([1, 2, 3, 4], function(n) { - * return n % 2 == 1; - * }); - * // => 3 - */ -var findLast = createFind(baseEachRight, true); - -export default findLast; diff --git a/collection/findWhere.js b/collection/findWhere.js deleted file mode 100644 index ac4b6bde9..000000000 --- a/collection/findWhere.js +++ /dev/null @@ -1,37 +0,0 @@ -import baseMatches from '../internal/baseMatches'; -import find from './find'; - -/** - * Performs a deep comparison between each element in `collection` and the - * source object, returning the first element that has equivalent property - * values. - * - * **Note:** This method supports comparing arrays, booleans, `Date` objects, - * numbers, `Object` objects, regexes, and strings. Objects are compared by - * their own, not inherited, enumerable properties. For comparing a single - * own or inherited property value see `_.matchesProperty`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to search. - * @param {Object} source The object of property values to match. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false } - * ]; - * - * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user'); - * // => 'barney' - * - * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user'); - * // => 'fred' - */ -function findWhere(collection, source) { - return find(collection, baseMatches(source)); -} - -export default findWhere; diff --git a/collection/foldl.js b/collection/foldl.js deleted file mode 100644 index 83cfab772..000000000 --- a/collection/foldl.js +++ /dev/null @@ -1,2 +0,0 @@ -import reduce from './reduce' -export default reduce; diff --git a/collection/foldr.js b/collection/foldr.js deleted file mode 100644 index cbd7db3fa..000000000 --- a/collection/foldr.js +++ /dev/null @@ -1,2 +0,0 @@ -import reduceRight from './reduceRight' -export default reduceRight; diff --git a/collection/forEach.js b/collection/forEach.js deleted file mode 100644 index 8202a9ac2..000000000 --- a/collection/forEach.js +++ /dev/null @@ -1,37 +0,0 @@ -import arrayEach from '../internal/arrayEach'; -import baseEach from '../internal/baseEach'; -import createForEach from '../internal/createForEach'; - -/** - * Iterates over elements of `collection` invoking `iteratee` for each element. - * The `iteratee` is bound to `thisArg` and invoked with three arguments: - * (value, index|key, collection). Iteratee functions may exit iteration early - * by explicitly returning `false`. - * - * **Note:** As with other "Collections" methods, objects with a "length" property - * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` - * may be used for object iteration. - * - * @static - * @memberOf _ - * @alias each - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array|Object|string} Returns `collection`. - * @example - * - * _([1, 2]).forEach(function(n) { - * console.log(n); - * }).value(); - * // => logs each value from left to right and returns the array - * - * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) { - * console.log(n, key); - * }); - * // => logs each value-key pair and returns the object (iteration order is not guaranteed) - */ -var forEach = createForEach(arrayEach, baseEach); - -export default forEach; diff --git a/collection/forEachRight.js b/collection/forEachRight.js deleted file mode 100644 index 896b00a1b..000000000 --- a/collection/forEachRight.js +++ /dev/null @@ -1,26 +0,0 @@ -import arrayEachRight from '../internal/arrayEachRight'; -import baseEachRight from '../internal/baseEachRight'; -import createForEach from '../internal/createForEach'; - -/** - * This method is like `_.forEach` except that it iterates over elements of - * `collection` from right to left. - * - * @static - * @memberOf _ - * @alias eachRight - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array|Object|string} Returns `collection`. - * @example - * - * _([1, 2]).forEachRight(function(n) { - * console.log(n); - * }).value(); - * // => logs each value from right to left and returns the array - */ -var forEachRight = createForEach(arrayEachRight, baseEachRight); - -export default forEachRight; diff --git a/collection/groupBy.js b/collection/groupBy.js deleted file mode 100644 index 9cc51a745..000000000 --- a/collection/groupBy.js +++ /dev/null @@ -1,59 +0,0 @@ -import createAggregator from '../internal/createAggregator'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -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: - * (value, index|key, collection). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * _.groupBy([4.2, 6.1, 6.4], function(n) { - * return Math.floor(n); - * }); - * // => { '4': [4.2], '6': [6.1, 6.4] } - * - * _.groupBy([4.2, 6.1, 6.4], function(n) { - * return this.floor(n); - * }, Math); - * // => { '4': [4.2], '6': [6.1, 6.4] } - * - * // using the `_.property` callback shorthand - * _.groupBy(['one', 'two', 'three'], 'length'); - * // => { '3': ['one', 'two'], '5': ['three'] } - */ -var groupBy = createAggregator(function(result, value, key) { - if (hasOwnProperty.call(result, key)) { - result[key].push(value); - } else { - result[key] = [value]; - } -}); - -export default groupBy; diff --git a/collection/include.js b/collection/include.js deleted file mode 100644 index a1520e467..000000000 --- a/collection/include.js +++ /dev/null @@ -1,2 +0,0 @@ -import includes from './includes' -export default includes; diff --git a/collection/includes.js b/collection/includes.js deleted file mode 100644 index e72e35e8d..000000000 --- a/collection/includes.js +++ /dev/null @@ -1,57 +0,0 @@ -import baseIndexOf from '../internal/baseIndexOf'; -import getLength from '../internal/getLength'; -import isArray from '../lang/isArray'; -import isIterateeCall from '../internal/isIterateeCall'; -import isLength from '../internal/isLength'; -import isString from '../lang/isString'; -import values from '../object/values'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; - -/** - * Checks if `target` is in `collection` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * for equality comparisons. If `fromIndex` is negative, it's used as the offset - * from the end of `collection`. - * - * @static - * @memberOf _ - * @alias contains, include - * @category Collection - * @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 - * - * _.includes([1, 2, 3], 1); - * // => true - * - * _.includes([1, 2, 3], 1, 2); - * // => false - * - * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); - * // => true - * - * _.includes('pebbles', 'eb'); - * // => true - */ -function includes(collection, target, fromIndex, guard) { - var length = collection ? getLength(collection) : 0; - if (!isLength(length)) { - collection = values(collection); - length = collection.length; - } - 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) - : (!!length && baseIndexOf(collection, target, fromIndex) > -1); -} - -export default includes; diff --git a/collection/indexBy.js b/collection/indexBy.js deleted file mode 100644 index c848586b5..000000000 --- a/collection/indexBy.js +++ /dev/null @@ -1,53 +0,0 @@ -import createAggregator from '../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: - * (value, index|key, collection). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * var keyData = [ - * { 'dir': 'left', 'code': 97 }, - * { 'dir': 'right', 'code': 100 } - * ]; - * - * _.indexBy(keyData, 'dir'); - * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } - * - * _.indexBy(keyData, function(object) { - * return String.fromCharCode(object.code); - * }); - * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } - * - * _.indexBy(keyData, function(object) { - * return this.fromCharCode(object.code); - * }, String); - * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } - */ -var indexBy = createAggregator(function(result, value, key) { - result[key] = value; -}); - -export default indexBy; diff --git a/collection/inject.js b/collection/inject.js deleted file mode 100644 index 83cfab772..000000000 --- a/collection/inject.js +++ /dev/null @@ -1,2 +0,0 @@ -import reduce from './reduce' -export default reduce; diff --git a/collection/map.js b/collection/map.js deleted file mode 100644 index fb4bc37ff..000000000 --- a/collection/map.js +++ /dev/null @@ -1,68 +0,0 @@ -import arrayMap from '../internal/arrayMap'; -import baseCallback from '../internal/baseCallback'; -import baseMap from '../internal/baseMap'; -import isArray from '../lang/isArray'; - -/** - * 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). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * Many lodash methods are guarded to work as iteratees for methods like - * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. - * - * The guarded methods are: - * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, - * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, - * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, - * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, - * `sum`, `uniq`, and `words` - * - * @static - * @memberOf _ - * @alias collect - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array} Returns the new mapped array. - * @example - * - * function timesThree(n) { - * return n * 3; - * } - * - * _.map([1, 2], timesThree); - * // => [3, 6] - * - * _.map({ 'a': 1, 'b': 2 }, timesThree); - * // => [3, 6] (iteration order is not guaranteed) - * - * var users = [ - * { 'user': 'barney' }, - * { 'user': 'fred' } - * ]; - * - * // using the `_.property` callback shorthand - * _.map(users, 'user'); - * // => ['barney', 'fred'] - */ -function map(collection, iteratee, thisArg) { - var func = isArray(collection) ? arrayMap : baseMap; - iteratee = baseCallback(iteratee, thisArg, 3); - return func(collection, iteratee); -} - -export default map; diff --git a/collection/max.js b/collection/max.js deleted file mode 100644 index 29b9656bb..000000000 --- a/collection/max.js +++ /dev/null @@ -1,2 +0,0 @@ -import max from '../math/max' -export default max; diff --git a/collection/min.js b/collection/min.js deleted file mode 100644 index 9c8a91efd..000000000 --- a/collection/min.js +++ /dev/null @@ -1,2 +0,0 @@ -import min from '../math/min' -export default min; diff --git a/collection/partition.js b/collection/partition.js deleted file mode 100644 index df7438246..000000000 --- a/collection/partition.js +++ /dev/null @@ -1,66 +0,0 @@ -import createAggregator from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the array of grouped elements. - * @example - * - * _.partition([1, 2, 3], function(n) { - * return n % 2; - * }); - * // => [[1, 3], [2]] - * - * _.partition([1.2, 2.3, 3.4], function(n) { - * return this.floor(n) % 2; - * }, Math); - * // => [[1.2, 3.4], [2.3]] - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': false }, - * { 'user': 'fred', 'age': 40, 'active': true }, - * { 'user': 'pebbles', 'age': 1, 'active': false } - * ]; - * - * var mapper = function(array) { - * return _.pluck(array, 'user'); - * }; - * - * // using the `_.matches` callback shorthand - * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper); - * // => [['pebbles'], ['barney', 'fred']] - * - * // using the `_.matchesProperty` callback shorthand - * _.map(_.partition(users, 'active', false), mapper); - * // => [['barney', 'pebbles'], ['fred']] - * - * // using the `_.property` callback shorthand - * _.map(_.partition(users, 'active'), mapper); - * // => [['fred'], ['barney', 'pebbles']] - */ -var partition = createAggregator(function(result, value, key) { - result[key ? 0 : 1].push(value); -}, function() { return [[], []]; }); - -export default partition; diff --git a/collection/pluck.js b/collection/pluck.js deleted file mode 100644 index ffc64c861..000000000 --- a/collection/pluck.js +++ /dev/null @@ -1,31 +0,0 @@ -import map from './map'; -import property from '../utility/property'; - -/** - * Gets the property value of `path` from all elements in `collection`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|string} path The path of the property to pluck. - * @returns {Array} Returns the property values. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } - * ]; - * - * _.pluck(users, 'user'); - * // => ['barney', 'fred'] - * - * var userIndex = _.indexBy(users, 'user'); - * _.pluck(userIndex, 'age'); - * // => [36, 40] (iteration order is not guaranteed) - */ -function pluck(collection, path) { - return map(collection, property(path)); -} - -export default pluck; diff --git a/collection/reduce.js b/collection/reduce.js deleted file mode 100644 index 86d53b603..000000000 --- a/collection/reduce.js +++ /dev/null @@ -1,44 +0,0 @@ -import arrayReduce from '../internal/arrayReduce'; -import baseEach from '../internal/baseEach'; -import createReduce from '../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: - * (accumulator, value, index|key, collection). - * - * Many lodash methods are guarded to work as iteratees for methods like - * `_.reduce`, `_.reduceRight`, and `_.transform`. - * - * The guarded methods are: - * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`, - * and `sortByOrder` - * - * @static - * @memberOf _ - * @alias foldl, inject - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {*} Returns the accumulated value. - * @example - * - * _.reduce([1, 2], function(total, n) { - * return total + n; - * }); - * // => 3 - * - * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) { - * result[key] = n * 3; - * return result; - * }, {}); - * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed) - */ -var reduce = createReduce(arrayReduce, baseEach); - -export default reduce; diff --git a/collection/reduceRight.js b/collection/reduceRight.js deleted file mode 100644 index df78324f1..000000000 --- a/collection/reduceRight.js +++ /dev/null @@ -1,29 +0,0 @@ -import arrayReduceRight from '../internal/arrayReduceRight'; -import baseEachRight from '../internal/baseEachRight'; -import createReduce from '../internal/createReduce'; - -/** - * This method is like `_.reduce` except that it iterates over elements of - * `collection` from right to left. - * - * @static - * @memberOf _ - * @alias foldr - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {*} Returns the accumulated value. - * @example - * - * var array = [[0, 1], [2, 3], [4, 5]]; - * - * _.reduceRight(array, function(flattened, other) { - * return flattened.concat(other); - * }, []); - * // => [4, 5, 2, 3, 0, 1] - */ -var reduceRight = createReduce(arrayReduceRight, baseEachRight); - -export default reduceRight; diff --git a/collection/reject.js b/collection/reject.js deleted file mode 100644 index 2eba4273d..000000000 --- a/collection/reject.js +++ /dev/null @@ -1,50 +0,0 @@ -import arrayFilter from '../internal/arrayFilter'; -import baseCallback from '../internal/baseCallback'; -import baseFilter from '../internal/baseFilter'; -import isArray from '../lang/isArray'; - -/** - * The opposite of `_.filter`; this method returns the elements of `collection` - * that `predicate` does **not** return truthy for. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Array} Returns the new filtered array. - * @example - * - * _.reject([1, 2, 3, 4], function(n) { - * return n % 2 == 0; - * }); - * // => [1, 3] - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': false }, - * { 'user': 'fred', 'age': 40, 'active': true } - * ]; - * - * // using the `_.matches` callback shorthand - * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user'); - * // => ['barney'] - * - * // using the `_.matchesProperty` callback shorthand - * _.pluck(_.reject(users, 'active', false), 'user'); - * // => ['fred'] - * - * // using the `_.property` callback shorthand - * _.pluck(_.reject(users, 'active'), 'user'); - * // => ['barney'] - */ -function reject(collection, predicate, thisArg) { - var func = isArray(collection) ? arrayFilter : baseFilter; - predicate = baseCallback(predicate, thisArg, 3); - return func(collection, function(value, index, collection) { - return !predicate(value, index, collection); - }); -} - -export default reject; diff --git a/collection/sample.js b/collection/sample.js deleted file mode 100644 index f18dccd69..000000000 --- a/collection/sample.js +++ /dev/null @@ -1,50 +0,0 @@ -import baseRandom from '../internal/baseRandom'; -import isIterateeCall from '../internal/isIterateeCall'; -import toArray from '../lang/toArray'; -import toIterable from '../internal/toIterable'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMin = Math.min; - -/** - * Gets a random element or `n` random elements from a collection. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to sample. - * @param {number} [n] The number of elements to sample. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {*} Returns the random sample(s). - * @example - * - * _.sample([1, 2, 3, 4]); - * // => 2 - * - * _.sample([1, 2, 3, 4], 2); - * // => [3, 1] - */ -function sample(collection, n, guard) { - if (guard ? isIterateeCall(collection, n, guard) : n == null) { - collection = toIterable(collection); - var length = collection.length; - return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; - } - var index = -1, - result = toArray(collection), - length = result.length, - lastIndex = length - 1; - - n = nativeMin(n < 0 ? 0 : (+n || 0), length); - while (++index < n) { - var rand = baseRandom(index, lastIndex), - value = result[rand]; - - result[rand] = result[index]; - result[index] = value; - } - result.length = n; - return result; -} - -export default sample; diff --git a/collection/select.js b/collection/select.js deleted file mode 100644 index ccc6e071f..000000000 --- a/collection/select.js +++ /dev/null @@ -1,2 +0,0 @@ -import filter from './filter' -export default filter; diff --git a/collection/size.js b/collection/size.js deleted file mode 100644 index cb386c7c0..000000000 --- a/collection/size.js +++ /dev/null @@ -1,30 +0,0 @@ -import getLength from '../internal/getLength'; -import isLength from '../internal/isLength'; -import keys from '../object/keys'; - -/** - * Gets the size of `collection` by returning its length for array-like - * values or the number of own enumerable properties for objects. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to inspect. - * @returns {number} Returns the size of `collection`. - * @example - * - * _.size([1, 2, 3]); - * // => 3 - * - * _.size({ 'a': 1, 'b': 2 }); - * // => 2 - * - * _.size('pebbles'); - * // => 7 - */ -function size(collection) { - var length = collection ? getLength(collection) : 0; - return isLength(length) ? length : keys(collection).length; -} - -export default size; diff --git a/collection/some.js b/collection/some.js deleted file mode 100644 index 6cf382a53..000000000 --- a/collection/some.js +++ /dev/null @@ -1,67 +0,0 @@ -import arraySome from '../internal/arraySome'; -import baseCallback from '../internal/baseCallback'; -import baseSome from '../internal/baseSome'; -import isArray from '../lang/isArray'; -import isIterateeCall from '../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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @alias any - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. - * @example - * - * _.some([null, 0, 'yes', false], Boolean); - * // => true - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false } - * ]; - * - * // using the `_.matches` callback shorthand - * _.some(users, { 'user': 'barney', 'active': false }); - * // => false - * - * // using the `_.matchesProperty` callback shorthand - * _.some(users, 'active', false); - * // => true - * - * // using the `_.property` callback shorthand - * _.some(users, 'active'); - * // => true - */ -function some(collection, predicate, thisArg) { - var func = isArray(collection) ? arraySome : baseSome; - if (thisArg && isIterateeCall(collection, predicate, thisArg)) { - predicate = undefined; - } - if (typeof predicate != 'function' || thisArg !== undefined) { - predicate = baseCallback(predicate, thisArg, 3); - } - return func(collection, predicate); -} - -export default some; diff --git a/collection/sortBy.js b/collection/sortBy.js deleted file mode 100644 index 717f03851..000000000 --- a/collection/sortBy.js +++ /dev/null @@ -1,71 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import baseMap from '../internal/baseMap'; -import baseSortBy from '../internal/baseSortBy'; -import compareAscending from '../internal/compareAscending'; -import isIterateeCall from '../internal/isIterateeCall'; - -/** - * 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: - * (value, index|key, collection). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array} Returns the new sorted array. - * @example - * - * _.sortBy([1, 2, 3], function(n) { - * return Math.sin(n); - * }); - * // => [3, 1, 2] - * - * _.sortBy([1, 2, 3], function(n) { - * return this.sin(n); - * }, Math); - * // => [3, 1, 2] - * - * var users = [ - * { 'user': 'fred' }, - * { 'user': 'pebbles' }, - * { 'user': 'barney' } - * ]; - * - * // using the `_.property` callback shorthand - * _.pluck(_.sortBy(users, 'user'), 'user'); - * // => ['barney', 'fred', 'pebbles'] - */ -function sortBy(collection, iteratee, thisArg) { - if (collection == null) { - return []; - } - if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = undefined; - } - var index = -1; - iteratee = baseCallback(iteratee, thisArg, 3); - - var result = baseMap(collection, function(value, key, collection) { - return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value }; - }); - return baseSortBy(result, compareAscending); -} - -export default sortBy; diff --git a/collection/sortByAll.js b/collection/sortByAll.js deleted file mode 100644 index 49bb71141..000000000 --- a/collection/sortByAll.js +++ /dev/null @@ -1,52 +0,0 @@ -import baseFlatten from '../internal/baseFlatten'; -import baseSortByOrder from '../internal/baseSortByOrder'; -import isIterateeCall from '../internal/isIterateeCall'; -import restParam from '../function/restParam'; - -/** - * This method is like `_.sortBy` except that it can sort by multiple iteratees - * or property names. - * - * If a property name is provided for an iteratee the created `_.property` - * style callback returns the property value of the given element. - * - * If an object is provided for an iteratee the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees - * The iteratees to sort by, specified as individual values or arrays of values. - * @returns {Array} Returns the new sorted array. - * @example - * - * var users = [ - * { 'user': 'fred', 'age': 48 }, - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 42 }, - * { 'user': 'barney', 'age': 34 } - * ]; - * - * _.map(_.sortByAll(users, ['user', 'age']), _.values); - * // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]] - * - * _.map(_.sortByAll(users, 'user', function(chr) { - * return Math.floor(chr.age / 10); - * }), _.values); - * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] - */ -var sortByAll = restParam(function(collection, iteratees) { - if (collection == null) { - return []; - } - var guard = iteratees[2]; - if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { - iteratees.length = 1; - } - return baseSortByOrder(collection, baseFlatten(iteratees), []); -}); - -export default sortByAll; diff --git a/collection/sortByOrder.js b/collection/sortByOrder.js deleted file mode 100644 index ac30330f5..000000000 --- a/collection/sortByOrder.js +++ /dev/null @@ -1,55 +0,0 @@ -import baseSortByOrder from '../internal/baseSortByOrder'; -import isArray from '../lang/isArray'; -import isIterateeCall from '../internal/isIterateeCall'; - -/** - * This method is like `_.sortByAll` except that it allows specifying the - * sort orders of the iteratees to sort by. If `orders` is unspecified, all - * values are sorted in ascending order. Otherwise, a value is sorted in - * ascending order if its corresponding order is "asc", and descending if "desc". - * - * If a property name is provided for an iteratee the created `_.property` - * style callback returns the property value of the given element. - * - * If an object is provided for an iteratee the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {boolean[]} [orders] The sort orders of `iteratees`. - * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. - * @returns {Array} Returns the new sorted array. - * @example - * - * var users = [ - * { 'user': 'fred', 'age': 48 }, - * { 'user': 'barney', 'age': 34 }, - * { 'user': 'fred', 'age': 42 }, - * { 'user': 'barney', 'age': 36 } - * ]; - * - * // sort by `user` in ascending order and by `age` in descending order - * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values); - * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] - */ -function sortByOrder(collection, iteratees, orders, guard) { - if (collection == null) { - return []; - } - if (guard && isIterateeCall(iteratees, orders, guard)) { - orders = undefined; - } - if (!isArray(iteratees)) { - iteratees = iteratees == null ? [] : [iteratees]; - } - if (!isArray(orders)) { - orders = orders == null ? [] : [orders]; - } - return baseSortByOrder(collection, iteratees, orders); -} - -export default sortByOrder; diff --git a/collection/sum.js b/collection/sum.js deleted file mode 100644 index f4ad00270..000000000 --- a/collection/sum.js +++ /dev/null @@ -1,2 +0,0 @@ -import sum from '../math/sum' -export default sum; diff --git a/collection/where.js b/collection/where.js deleted file mode 100644 index f0dc1a3d9..000000000 --- a/collection/where.js +++ /dev/null @@ -1,37 +0,0 @@ -import baseMatches from '../internal/baseMatches'; -import filter from './filter'; - -/** - * Performs a deep comparison between each element in `collection` and the - * source object, returning an array of all elements that have equivalent - * property values. - * - * **Note:** This method supports comparing arrays, booleans, `Date` objects, - * numbers, `Object` objects, regexes, and strings. Objects are compared by - * their own, not inherited, enumerable properties. For comparing a single - * own or inherited property value see `_.matchesProperty`. - * - * @static - * @memberOf _ - * @category Collection - * @param {Array|Object|string} collection The collection to search. - * @param {Object} source The object of property values to match. - * @returns {Array} Returns the new filtered array. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] }, - * { 'user': 'fred', 'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] } - * ]; - * - * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user'); - * // => ['barney'] - * - * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user'); - * // => ['fred'] - */ -function where(collection, source) { - return filter(collection, baseMatches(source)); -} - -export default where; diff --git a/chain/wrapperCommit.js b/commit.js similarity index 88% rename from chain/wrapperCommit.js rename to commit.js index 9341c5ab2..c7f250229 100644 --- a/chain/wrapperCommit.js +++ b/commit.js @@ -1,11 +1,11 @@ -import LodashWrapper from '../internal/LodashWrapper'; +import LodashWrapper from './internal/LodashWrapper'; /** * Executes the chained sequence and returns the wrapped result. * * @name commit * @memberOf _ - * @category Chain + * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example * diff --git a/array/compact.js b/compact.js similarity index 100% rename from array/compact.js rename to compact.js diff --git a/concat.js b/concat.js new file mode 100644 index 000000000..1cd2dab4e --- /dev/null +++ b/concat.js @@ -0,0 +1,32 @@ +import arrayConcat from './internal/arrayConcat'; +import baseFlatten from './internal/baseFlatten'; +import isArray from './isArray'; +import rest from './rest'; + +/** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ +var concat = rest(function(array, values) { + values = baseFlatten(values); + return arrayConcat(isArray(array) ? array : [Object(array)], values); +}); + +export default concat; diff --git a/cond.js b/cond.js new file mode 100644 index 000000000..402859c90 --- /dev/null +++ b/cond.js @@ -0,0 +1,58 @@ +import apply from './internal/apply'; +import arrayMap from './internal/arrayMap'; +import baseIteratee from './internal/baseIteratee'; +import rest from './rest'; + +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a function that iterates over `pairs` invoking the corresponding + * function of the first predicate to return truthy. The predicate-function + * pairs are invoked with the `this` binding and arguments of the created + * function. + * + * @static + * @memberOf _ + * @category Util + * @param {Array} pairs The predicate-function pairs. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.cond([ + * [_.matches({ 'a': 1 }), _.constant('matches A')], + * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], + * [_.constant(true), _.constant('no match')] + * ]) + * + * func({ 'a': 1, 'b': 2 }); + * // => 'matches A' + * + * func({ 'a': 0, 'b': 1 }); + * // => 'matches B' + * + * func({ 'a': '1', 'b': '2' }); + * // => 'no match' + */ +function cond(pairs) { + var length = pairs ? pairs.length : 0; + + pairs = !length ? [] : arrayMap(pairs, function(pair) { + if (typeof pair[1] != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return [baseIteratee(pair[0]), pair[1]]; + }); + + return rest(function(args) { + var index = -1; + while (++index < length) { + var pair = pairs[index]; + if (apply(pair[0], this, args)) { + return apply(pair[1], this, args); + } + } + }); +} + +export default cond; diff --git a/conforms.js b/conforms.js new file mode 100644 index 000000000..e90dca164 --- /dev/null +++ b/conforms.js @@ -0,0 +1,28 @@ +import baseClone from './internal/baseClone'; +import baseConforms from './internal/baseConforms'; + +/** + * Creates a function that invokes the predicate properties of `source` with + * the corresponding property values of a given object, returning `true` if + * all predicates return truthy, else `false`. + * + * @static + * @memberOf _ + * @category Util + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new function. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * _.filter(users, _.conforms({ 'age': _.partial(_.gt, _, 38) })); + * // => [{ 'user': 'fred', 'age': 40 }] + */ +function conforms(source) { + return baseConforms(baseClone(source, true)); +} + +export default conforms; diff --git a/utility/constant.js b/constant.js similarity index 95% rename from utility/constant.js rename to constant.js index 910042b4e..6392cde9f 100644 --- a/utility/constant.js +++ b/constant.js @@ -3,7 +3,7 @@ * * @static * @memberOf _ - * @category Utility + * @category Util * @param {*} value The value to return from the new function. * @returns {Function} Returns the new function. * @example diff --git a/countBy.js b/countBy.js new file mode 100644 index 000000000..23d81a76b --- /dev/null +++ b/countBy.js @@ -0,0 +1,33 @@ +import createAggregator from './internal/createAggregator'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +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 invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ +var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); +}); + +export default countBy; diff --git a/object/create.js b/create.js similarity index 55% rename from object/create.js rename to create.js index 2cec13935..ef18b9074 100644 --- a/object/create.js +++ b/create.js @@ -1,18 +1,15 @@ -import baseAssign from '../internal/baseAssign'; -import baseCreate from '../internal/baseCreate'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseAssign from './internal/baseAssign'; +import baseCreate from './internal/baseCreate'; /** - * Creates an object that inherits from the given `prototype` object. If a - * `properties` object is provided its own enumerable properties are assigned - * to the created object. + * Creates an object that inherits from the `prototype` object. If a `properties` + * object is provided its own enumerable properties are assigned to the created object. * * @static * @memberOf _ * @category Object * @param {Object} prototype The object to inherit from. * @param {Object} [properties] The properties to assign to the object. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Object} Returns the new object. * @example * @@ -36,11 +33,8 @@ import isIterateeCall from '../internal/isIterateeCall'; * circle instanceof Shape; * // => true */ -function create(prototype, properties, guard) { +function create(prototype, properties) { var result = baseCreate(prototype); - if (guard && isIterateeCall(prototype, properties, guard)) { - properties = undefined; - } return properties ? baseAssign(result, properties) : result; } diff --git a/curry.js b/curry.js new file mode 100644 index 000000000..318864915 --- /dev/null +++ b/curry.js @@ -0,0 +1,53 @@ +import createWrapper from './internal/createWrapper'; + +/** Used to compose bitmasks for wrapper metadata. */ +var CURRY_FLAG = 8; + +/** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // using placeholders + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ +function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrapper(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; +} + +export default curry; diff --git a/function/curryRight.js b/curryRight.js similarity index 66% rename from function/curryRight.js rename to curryRight.js index 8cd0edac0..05d230cad 100644 --- a/function/curryRight.js +++ b/curryRight.js @@ -1,4 +1,4 @@ -import createCurry from '../internal/createCurry'; +import createWrapper from './internal/createWrapper'; /** Used to compose bitmasks for wrapper metadata. */ var CURRY_RIGHT_FLAG = 16; @@ -10,14 +10,14 @@ var CURRY_RIGHT_FLAG = 16; * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for provided arguments. * - * **Note:** This method does not set the "length" property of curried functions. + * **Note:** This method doesn't set the "length" property of curried functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Function} Returns the new curried function. * @example * @@ -40,9 +40,11 @@ var CURRY_RIGHT_FLAG = 16; * curried(3)(1, _)(2); * // => [1, 2, 3] */ -var curryRight = createCurry(CURRY_RIGHT_FLAG); - -// Assign default placeholders. -curryRight.placeholder = {}; +function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrapper(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; +} export default curryRight; diff --git a/date.default.js b/date.default.js new file mode 100644 index 000000000..d03070153 --- /dev/null +++ b/date.default.js @@ -0,0 +1,5 @@ +import now from './now'; + +export default { + now +}; diff --git a/date.js b/date.js index 9fa88963c..d5c560b51 100644 --- a/date.js +++ b/date.js @@ -1,5 +1,2 @@ -import now from './date/now'; - -export default { - 'now': now -}; +export { default as now } from './now'; +export { default as default } from './date.default'; diff --git a/date/now.js b/date/now.js deleted file mode 100644 index 7c94a3021..000000000 --- a/date/now.js +++ /dev/null @@ -1,24 +0,0 @@ -import getNative from '../internal/getNative'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeNow = getNative(Date, 'now'); - -/** - * Gets the number of milliseconds that have elapsed since the Unix epoch - * (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @category Date - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => logs the number of milliseconds it took for the deferred function to be invoked - */ -var now = nativeNow || function() { - return new Date().getTime(); -}; - -export default now; diff --git a/function/debounce.js b/debounce.js similarity index 73% rename from function/debounce.js rename to debounce.js index 88083f271..8d2a325a6 100644 --- a/function/debounce.js +++ b/debounce.js @@ -1,20 +1,22 @@ -import isObject from '../lang/isObject'; -import now from '../date/now'; +import isObject from './isObject'; +import now from './now'; +import toNumber from './toNumber'; /** 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. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; /** * Creates a debounced function that delays invoking `func` until after `wait` * milliseconds have elapsed since the last time the debounced function was * invoked. The debounced function comes with a `cancel` method to cancel - * delayed invocations. Provide an options object to indicate that `func` - * should be invoked on the leading and/or trailing edge of the `wait` timeout. - * Subsequent calls to the debounced function return the result of the last - * `func` invocation. + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide an options object to indicate whether `func` should be invoked on + * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent calls + * to the debounced function return the result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the debounced function is @@ -41,34 +43,19 @@ var nativeMax = Math.max; * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * - * // invoke `sendMail` when the click event is fired, debouncing subsequent calls - * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { + * // invoke `sendMail` when clicked, debouncing subsequent calls + * jQuery(element).on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })); * * // ensure `batchLog` is invoked once after 1 second of debounced calls + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); * var source = new EventSource('/stream'); - * jQuery(source).on('message', _.debounce(batchLog, 250, { - * 'maxWait': 1000 - * })); + * jQuery(source).on('message', debounced); * - * // cancel a debounced call - * var todoChanges = _.debounce(batchLog, 1000); - * Object.observe(models.todo, todoChanges); - * - * Object.observe(models, function(changes) { - * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { - * todoChanges.cancel(); - * } - * }, ['delete']); - * - * // ...at some point `models.todo` is changed - * models.todo.completed = true; - * - * // ...before 1 second has passed `models.todo` is deleted - * // which cancels the debounced `todoChanges` call - * delete models.todo; + * // cancel a trailing debounced invocation + * jQuery(window).on('popstate', debounced.cancel); */ function debounce(func, wait, options) { var args, @@ -79,19 +66,17 @@ function debounce(func, wait, options) { timeoutId, trailingCall, lastCalled = 0, + leading = false, maxWait = false, trailing = true; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - wait = wait < 0 ? 0 : (+wait || 0); - if (options === true) { - var leading = true; - trailing = false; - } else if (isObject(options)) { + wait = toNumber(wait) || 0; + if (isObject(options)) { leading = !!options.leading; - maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); + maxWait = 'maxWait' in options && nativeMax(toNumber(options.maxWait) || 0, wait); trailing = 'trailing' in options ? !!options.trailing : trailing; } @@ -103,7 +88,7 @@ function debounce(func, wait, options) { clearTimeout(maxTimeoutId); } lastCalled = 0; - maxTimeoutId = timeoutId = trailingCall = undefined; + args = maxTimeoutId = thisArg = timeoutId = trailingCall = undefined; } function complete(isCalled, id) { @@ -129,6 +114,14 @@ function debounce(func, wait, options) { } } + function flush() { + if ((timeoutId && trailingCall) || (maxTimeoutId && trailing)) { + result = func.apply(thisArg, args); + } + cancel(); + return result; + } + function maxDelayed() { complete(trailing, timeoutId); } @@ -175,6 +168,7 @@ function debounce(func, wait, options) { return result; } debounced.cancel = cancel; + debounced.flush = flush; return debounced; } diff --git a/string/deburr.js b/deburr.js similarity index 71% rename from string/deburr.js rename to deburr.js index 88d3573e8..36569e4c3 100644 --- a/string/deburr.js +++ b/deburr.js @@ -1,12 +1,18 @@ -import baseToString from '../internal/baseToString'; -import deburrLetter from '../internal/deburrLetter'; - -/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ -var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; +import deburrLetter from './internal/deburrLetter'; +import toString from './toString'; /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; +/** Used to compose unicode character classes. */ +var rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23'; + +/** Used to compose unicode capture groups. */ +var rsCombo = '[' + rsComboRange + ']'; + +/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ +var reComboMark = RegExp(rsCombo, 'g'); + /** * 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). @@ -22,7 +28,7 @@ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; * // => 'deja vu' */ function deburr(string) { - string = baseToString(string); + string = toString(string); return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ''); } diff --git a/defaults.js b/defaults.js new file mode 100644 index 000000000..63e3df637 --- /dev/null +++ b/defaults.js @@ -0,0 +1,30 @@ +import apply from './internal/apply'; +import assignInDefaults from './internal/assignInDefaults'; +import assignInWith from './assignInWith'; +import rest from './rest'; + +/** + * Assigns own and inherited enumerable properties of source objects to the + * destination object for all destination properties that resolve to `undefined`. + * Source objects are applied from left to right. Once a property is set, + * additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); + * // => { 'user': 'barney', 'age': 36 } + */ +var defaults = rest(function(args) { + args.push(undefined, assignInDefaults); + return apply(assignInWith, undefined, args); +}); + +export default defaults; diff --git a/object/defaultsDeep.js b/defaultsDeep.js similarity index 65% rename from object/defaultsDeep.js rename to defaultsDeep.js index 21c73b3b5..f7f8d4bc9 100644 --- a/object/defaultsDeep.js +++ b/defaultsDeep.js @@ -1,6 +1,7 @@ -import createDefaults from '../internal/createDefaults'; -import merge from './merge'; -import mergeDefaults from '../internal/mergeDefaults'; +import apply from './internal/apply'; +import mergeDefaults from './internal/mergeDefaults'; +import mergeWith from './mergeWith'; +import rest from './rest'; /** * This method is like `_.defaults` except that it recursively assigns @@ -20,6 +21,9 @@ import mergeDefaults from '../internal/mergeDefaults'; * // => { 'user': { 'name': 'barney', 'age': 36 } } * */ -var defaultsDeep = createDefaults(merge, mergeDefaults); +var defaultsDeep = rest(function(args) { + args.push(undefined, mergeDefaults); + return apply(mergeWith, undefined, args); +}); export default defaultsDeep; diff --git a/function/defer.js b/defer.js similarity index 71% rename from function/defer.js rename to defer.js index 757de6de0..ed4f5e343 100644 --- a/function/defer.js +++ b/defer.js @@ -1,5 +1,5 @@ -import baseDelay from '../internal/baseDelay'; -import restParam from './restParam'; +import baseDelay from './internal/baseDelay'; +import rest from './rest'; /** * Defers invoking the `func` until the current call stack has cleared. Any @@ -9,7 +9,7 @@ import restParam from './restParam'; * @memberOf _ * @category Function * @param {Function} func The function to defer. - * @param {...*} [args] The arguments to invoke the function with. + * @param {...*} [args] The arguments to invoke `func` with. * @returns {number} Returns the timer id. * @example * @@ -18,7 +18,7 @@ import restParam from './restParam'; * }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ -var defer = restParam(function(func, args) { +var defer = rest(function(func, args) { return baseDelay(func, 1, args); }); diff --git a/function/delay.js b/delay.js similarity index 64% rename from function/delay.js rename to delay.js index 5b34c6912..9112fb5de 100644 --- a/function/delay.js +++ b/delay.js @@ -1,5 +1,6 @@ -import baseDelay from '../internal/baseDelay'; -import restParam from './restParam'; +import baseDelay from './internal/baseDelay'; +import rest from './rest'; +import toNumber from './toNumber'; /** * Invokes `func` after `wait` milliseconds. Any additional arguments are @@ -10,7 +11,7 @@ import restParam from './restParam'; * @category Function * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. - * @param {...*} [args] The arguments to invoke the function with. + * @param {...*} [args] The arguments to invoke `func` with. * @returns {number} Returns the timer id. * @example * @@ -19,8 +20,8 @@ import restParam from './restParam'; * }, 1000, 'later'); * // => logs 'later' after one second */ -var delay = restParam(function(func, wait, args) { - return baseDelay(func, wait, args); +var delay = rest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); }); export default delay; diff --git a/array/difference.js b/difference.js similarity index 50% rename from array/difference.js rename to difference.js index 64a541bd7..53bbe28ae 100644 --- a/array/difference.js +++ b/difference.js @@ -1,8 +1,7 @@ -import baseDifference from '../internal/baseDifference'; -import baseFlatten from '../internal/baseFlatten'; -import isArrayLike from '../internal/isArrayLike'; -import isObjectLike from '../internal/isObjectLike'; -import restParam from '../function/restParam'; +import baseDifference from './internal/baseDifference'; +import baseFlatten from './internal/baseFlatten'; +import isArrayLikeObject from './isArrayLikeObject'; +import rest from './rest'; /** * Creates an array of unique `array` values not included in the other @@ -13,15 +12,15 @@ import restParam from '../function/restParam'; * @memberOf _ * @category Array * @param {Array} array The array to inspect. - * @param {...Array} [values] The arrays of values to exclude. + * @param {...Array} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. * @example * - * _.difference([1, 2, 3], [4, 2]); - * // => [1, 3] + * _.difference([3, 2, 1], [4, 2]); + * // => [3, 1] */ -var difference = restParam(function(array, values) { - return (isObjectLike(array) && isArrayLike(array)) +var difference = rest(function(array, values) { + return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; }); diff --git a/differenceBy.js b/differenceBy.js new file mode 100644 index 000000000..d101dd25e --- /dev/null +++ b/differenceBy.js @@ -0,0 +1,39 @@ +import baseDifference from './internal/baseDifference'; +import baseFlatten from './internal/baseFlatten'; +import baseIteratee from './internal/baseIteratee'; +import isArrayLikeObject from './isArrayLikeObject'; +import last from './last'; +import rest from './rest'; + +/** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor); + * // => [3.1, 1.3] + * + * // using the `_.property` iteratee shorthand + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ +var differenceBy = rest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, false, true), baseIteratee(iteratee)) + : []; +}); + +export default differenceBy; diff --git a/differenceWith.js b/differenceWith.js new file mode 100644 index 000000000..7f573cc62 --- /dev/null +++ b/differenceWith.js @@ -0,0 +1,36 @@ +import baseDifference from './internal/baseDifference'; +import baseFlatten from './internal/baseFlatten'; +import isArrayLikeObject from './isArrayLikeObject'; +import last from './last'; +import rest from './rest'; + +/** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ +var differenceWith = rest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, false, true), undefined, comparator) + : []; +}); + +export default differenceWith; diff --git a/array/drop.js b/drop.js similarity index 66% rename from array/drop.js rename to drop.js index bbb1cc162..3afb5d785 100644 --- a/array/drop.js +++ b/drop.js @@ -1,5 +1,5 @@ -import baseSlice from '../internal/baseSlice'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseSlice from './internal/baseSlice'; +import toInteger from './toInteger'; /** * Creates a slice of `array` with `n` elements dropped from the beginning. @@ -9,7 +9,7 @@ import isIterateeCall from '../internal/isIterateeCall'; * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -30,10 +30,8 @@ function drop(array, n, guard) { if (!length) { return []; } - if (guard ? isIterateeCall(array, n, guard) : n == null) { - n = 1; - } - return baseSlice(array, n < 0 ? 0 : n); + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); } export default drop; diff --git a/array/dropRight.js b/dropRight.js similarity index 69% rename from array/dropRight.js rename to dropRight.js index 96dfebb1f..67b3b32fe 100644 --- a/array/dropRight.js +++ b/dropRight.js @@ -1,5 +1,5 @@ -import baseSlice from '../internal/baseSlice'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseSlice from './internal/baseSlice'; +import toInteger from './toInteger'; /** * Creates a slice of `array` with `n` elements dropped from the end. @@ -9,7 +9,7 @@ import isIterateeCall from '../internal/isIterateeCall'; * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -30,10 +30,8 @@ function dropRight(array, n, guard) { if (!length) { return []; } - if (guard ? isIterateeCall(array, n, guard) : n == null) { - n = 1; - } - n = length - (+n || 0); + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; return baseSlice(array, 0, n < 0 ? 0 : n); } diff --git a/dropRightWhile.js b/dropRightWhile.js new file mode 100644 index 000000000..43067e75e --- /dev/null +++ b/dropRightWhile.js @@ -0,0 +1,44 @@ +import baseIteratee from './internal/baseIteratee'; +import baseWhile from './internal/baseWhile'; + +/** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // using the `_.matches` iteratee shorthand + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // using the `_.property` iteratee shorthand + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ +function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, baseIteratee(predicate, 3), true, true) + : []; +} + +export default dropRightWhile; diff --git a/dropWhile.js b/dropWhile.js new file mode 100644 index 000000000..211ad3c82 --- /dev/null +++ b/dropWhile.js @@ -0,0 +1,44 @@ +import baseIteratee from './internal/baseIteratee'; +import baseWhile from './internal/baseWhile'; + +/** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // using the `_.matches` iteratee shorthand + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // using the `_.property` iteratee shorthand + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ +function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, baseIteratee(predicate, 3), true) + : []; +} + +export default dropWhile; diff --git a/each.js b/each.js new file mode 100644 index 000000000..388824242 --- /dev/null +++ b/each.js @@ -0,0 +1 @@ +export { default } from './forEach' diff --git a/eachRight.js b/eachRight.js new file mode 100644 index 000000000..72ac72ab9 --- /dev/null +++ b/eachRight.js @@ -0,0 +1 @@ +export { default } from './forEachRight' diff --git a/string/endsWith.js b/endsWith.js similarity index 73% rename from string/endsWith.js rename to endsWith.js index 217efb714..851d42664 100644 --- a/string/endsWith.js +++ b/endsWith.js @@ -1,7 +1,6 @@ -import baseToString from '../internal/baseToString'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMin = Math.min; +import baseClamp from './internal/baseClamp'; +import toInteger from './toInteger'; +import toString from './toString'; /** * Checks if `string` ends with the given target string. @@ -25,13 +24,13 @@ var nativeMin = Math.min; * // => true */ function endsWith(string, target, position) { - string = baseToString(string); - target = (target + ''); + string = toString(string); + target = typeof target == 'string' ? target : (target + ''); var length = string.length; position = position === undefined ? length - : nativeMin(position < 0 ? 0 : (+position || 0), length); + : baseClamp(toInteger(position), 0, length); position -= target.length; return position >= 0 && string.indexOf(target, position) == position; diff --git a/eq.js b/eq.js new file mode 100644 index 000000000..f3cb7ea4a --- /dev/null +++ b/eq.js @@ -0,0 +1,35 @@ +/** + * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'user': 'fred' }; + * var other = { 'user': 'fred' }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +export default eq; diff --git a/string/escape.js b/escape.js similarity index 72% rename from string/escape.js rename to escape.js index feaa8f7a7..5ca549509 100644 --- a/string/escape.js +++ b/escape.js @@ -1,16 +1,16 @@ -import baseToString from '../internal/baseToString'; -import escapeHtmlChar from '../internal/escapeHtmlChar'; +import escapeHtmlChar from './internal/escapeHtmlChar'; +import toString from './toString'; /** Used to match HTML entities and HTML characters. */ var reUnescapedHtml = /[&<>"'`]/g, reHasUnescapedHtml = RegExp(reUnescapedHtml.source); /** - * Converts the characters "&", "<", ">", '"', "'", and "\`", in `string` to + * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to * their corresponding HTML entities. * - * **Note:** No other characters are escaped. To escape additional characters - * use a third-party library like [_he_](https://mths.be/he). + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). * * Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't need escaping in HTML and have no special meaning @@ -18,8 +18,8 @@ var reUnescapedHtml = /[&<>"'`]/g, * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * - * Backticks are escaped because in Internet Explorer < 9, they can break out - * of attribute values or HTML comments. See [#59](https://html5sec.org/#59), + * Backticks are escaped because in IE < 9, they can break out of + * attribute values or HTML comments. See [#59](https://html5sec.org/#59), * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/) * for more details. @@ -38,8 +38,7 @@ var reUnescapedHtml = /[&<>"'`]/g, * // => 'fred, barney, & pebbles' */ function escape(string) { - // Reset `lastIndex` because in IE < 9 `String#replace` does not. - string = baseToString(string); + string = toString(string); return (string && reHasUnescapedHtml.test(string)) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; diff --git a/escapeRegExp.js b/escapeRegExp.js new file mode 100644 index 000000000..47fec43f6 --- /dev/null +++ b/escapeRegExp.js @@ -0,0 +1,28 @@ +import toString from './toString'; + +/** Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + +/** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ +function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; +} + +export default escapeRegExp; diff --git a/every.js b/every.js new file mode 100644 index 000000000..ebaafe05e --- /dev/null +++ b/every.js @@ -0,0 +1,49 @@ +import arrayEvery from './internal/arrayEvery'; +import baseEvery from './internal/baseEvery'; +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; +import isIterateeCall from './internal/isIterateeCall'; + +/** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // using the `_.matches` iteratee shorthand + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // using the `_.matchesProperty` iteratee shorthand + * _.every(users, ['active', false]); + * // => true + * + * // using the `_.property` iteratee shorthand + * _.every(users, 'active'); + * // => false + */ +function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, baseIteratee(predicate, 3)); +} + +export default every; diff --git a/array/fill.js b/fill.js similarity index 84% rename from array/fill.js rename to fill.js index dc8d4fa90..2a337d1d6 100644 --- a/array/fill.js +++ b/fill.js @@ -1,5 +1,5 @@ -import baseFill from '../internal/baseFill'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseFill from './internal/baseFill'; +import isIterateeCall from './internal/isIterateeCall'; /** * Fills elements of `array` with `value` from `start` up to, but not @@ -26,8 +26,8 @@ import isIterateeCall from '../internal/isIterateeCall'; * _.fill(Array(3), 2); * // => [2, 2, 2] * - * _.fill([4, 6, 8], '*', 1, 2); - * // => [4, '*', 8] + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] */ function fill(array, value, start, end) { var length = array ? array.length : 0; diff --git a/filter.js b/filter.js new file mode 100644 index 000000000..cfa0844ae --- /dev/null +++ b/filter.js @@ -0,0 +1,44 @@ +import arrayFilter from './internal/arrayFilter'; +import baseFilter from './internal/baseFilter'; +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; + +/** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three arguments: + * (value, index|key, collection). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // using the `_.matches` iteratee shorthand + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // using the `_.property` iteratee shorthand + * _.filter(users, 'active'); + * // => objects for ['barney'] + */ +function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, baseIteratee(predicate, 3)); +} + +export default filter; diff --git a/find.js b/find.js new file mode 100644 index 000000000..bfabb403d --- /dev/null +++ b/find.js @@ -0,0 +1,50 @@ +import baseEach from './internal/baseEach'; +import baseFind from './internal/baseFind'; +import baseFindIndex from './internal/baseFindIndex'; +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; + +/** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three arguments: + * (value, index|key, collection). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // using the `_.matches` iteratee shorthand + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // using the `_.matchesProperty` iteratee shorthand + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // using the `_.property` iteratee shorthand + * _.find(users, 'active'); + * // => object for 'barney' + */ +function find(collection, predicate) { + predicate = baseIteratee(predicate, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, baseEach); +} + +export default find; diff --git a/findIndex.js b/findIndex.js new file mode 100644 index 000000000..73a133d90 --- /dev/null +++ b/findIndex.js @@ -0,0 +1,43 @@ +import baseFindIndex from './internal/baseFindIndex'; +import baseIteratee from './internal/baseIteratee'; + +/** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // using the `_.matches` iteratee shorthand + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // using the `_.matchesProperty` iteratee shorthand + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // using the `_.property` iteratee shorthand + * _.findIndex(users, 'active'); + * // => 2 + */ +function findIndex(array, predicate) { + return (array && array.length) + ? baseFindIndex(array, baseIteratee(predicate, 3)) + : -1; +} + +export default findIndex; diff --git a/findKey.js b/findKey.js new file mode 100644 index 000000000..c7b1b31ca --- /dev/null +++ b/findKey.js @@ -0,0 +1,42 @@ +import baseFind from './internal/baseFind'; +import baseForOwn from './internal/baseForOwn'; +import baseIteratee from './internal/baseIteratee'; + +/** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // using the `_.matches` iteratee shorthand + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // using the `_.matchesProperty` iteratee shorthand + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // using the `_.property` iteratee shorthand + * _.findKey(users, 'active'); + * // => 'barney' + */ +function findKey(object, predicate) { + return baseFind(object, baseIteratee(predicate, 3), baseForOwn, true); +} + +export default findKey; diff --git a/findLast.js b/findLast.js new file mode 100644 index 000000000..5ada5d872 --- /dev/null +++ b/findLast.js @@ -0,0 +1,33 @@ +import baseEachRight from './internal/baseEachRight'; +import baseFind from './internal/baseFind'; +import baseFindIndex from './internal/baseFindIndex'; +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; + +/** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ +function findLast(collection, predicate) { + predicate = baseIteratee(predicate, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, true); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, baseEachRight); +} + +export default findLast; diff --git a/findLastIndex.js b/findLastIndex.js new file mode 100644 index 000000000..51cb671fd --- /dev/null +++ b/findLastIndex.js @@ -0,0 +1,43 @@ +import baseFindIndex from './internal/baseFindIndex'; +import baseIteratee from './internal/baseIteratee'; + +/** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // using the `_.matches` iteratee shorthand + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // using the `_.matchesProperty` iteratee shorthand + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // using the `_.property` iteratee shorthand + * _.findLastIndex(users, 'active'); + * // => 0 + */ +function findLastIndex(array, predicate) { + return (array && array.length) + ? baseFindIndex(array, baseIteratee(predicate, 3), true) + : -1; +} + +export default findLastIndex; diff --git a/findLastKey.js b/findLastKey.js new file mode 100644 index 000000000..4d59c9131 --- /dev/null +++ b/findLastKey.js @@ -0,0 +1,42 @@ +import baseFind from './internal/baseFind'; +import baseForOwnRight from './internal/baseForOwnRight'; +import baseIteratee from './internal/baseIteratee'; + +/** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // using the `_.matches` iteratee shorthand + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // using the `_.matchesProperty` iteratee shorthand + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // using the `_.property` iteratee shorthand + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ +function findLastKey(object, predicate) { + return baseFind(object, baseIteratee(predicate, 3), baseForOwnRight, true); +} + +export default findLastKey; diff --git a/flatMap.js b/flatMap.js new file mode 100644 index 000000000..c3e08d8ee --- /dev/null +++ b/flatMap.js @@ -0,0 +1,30 @@ +import arrayMap from './internal/arrayMap'; +import baseFlatten from './internal/baseFlatten'; +import baseIteratee from './internal/baseIteratee'; + +/** + * Creates an array of flattened values by running each element in `array` + * through `iteratee` and concating its result to the other mapped values. + * The iteratee is invoked with three arguments: (value, index|key, array). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ +function flatMap(array, iteratee) { + var length = array ? array.length : 0; + return length ? baseFlatten(arrayMap(array, baseIteratee(iteratee, 3))) : []; +} + +export default flatMap; diff --git a/flatten.js b/flatten.js new file mode 100644 index 000000000..bbf0d8698 --- /dev/null +++ b/flatten.js @@ -0,0 +1,21 @@ +import baseFlatten from './internal/baseFlatten'; + +/** + * Flattens `array` a single level. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, 3, [4]]]); + * // => [1, 2, 3, [4]] + */ +function flatten(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array) : []; +} + +export default flatten; diff --git a/array/flattenDeep.js b/flattenDeep.js similarity index 75% rename from array/flattenDeep.js rename to flattenDeep.js index c9e3a9172..b617d7233 100644 --- a/array/flattenDeep.js +++ b/flattenDeep.js @@ -1,7 +1,7 @@ -import baseFlatten from '../internal/baseFlatten'; +import baseFlatten from './internal/baseFlatten'; /** - * Recursively flattens a nested array. + * This method is like `_.flatten` except that it recursively flattens `array`. * * @static * @memberOf _ diff --git a/flip.js b/flip.js new file mode 100644 index 000000000..0972af36d --- /dev/null +++ b/flip.js @@ -0,0 +1,27 @@ +import createWrapper from './internal/createWrapper'; + +/** Used to compose bitmasks for wrapper metadata. */ +var FLIP_FLAG = 512; + +/** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ +function flip(func) { + return createWrapper(func, FLIP_FLAG); +} + +export default flip; diff --git a/math/floor.js b/floor.js similarity index 70% rename from math/floor.js rename to floor.js index bfb24e660..93f895f58 100644 --- a/math/floor.js +++ b/floor.js @@ -1,12 +1,12 @@ -import createRound from '../internal/createRound'; +import createRound from './internal/createRound'; /** - * Calculates `n` rounded down to `precision`. + * Computes `number` rounded down to `precision`. * * @static * @memberOf _ * @category Math - * @param {number} n The number to round down. + * @param {number} number The number to round down. * @param {number} [precision=0] The precision to round down to. * @returns {number} Returns the rounded down number. * @example diff --git a/function/flow.js b/flow.js similarity index 78% rename from function/flow.js rename to flow.js index e5edf51f2..50ebf7ec6 100644 --- a/function/flow.js +++ b/flow.js @@ -1,4 +1,4 @@ -import createFlow from '../internal/createFlow'; +import createFlow from './internal/createFlow'; /** * Creates a function that returns the result of invoking the provided @@ -7,8 +7,8 @@ import createFlow from '../internal/createFlow'; * * @static * @memberOf _ - * @category Function - * @param {...Function} [funcs] Functions to invoke. + * @category Util + * @param {...(Function|Function[])} [funcs] Functions to invoke. * @returns {Function} Returns the new function. * @example * diff --git a/function/flowRight.js b/flowRight.js similarity index 73% rename from function/flowRight.js rename to flowRight.js index 861995144..26c0c8321 100644 --- a/function/flowRight.js +++ b/flowRight.js @@ -1,4 +1,4 @@ -import createFlow from '../internal/createFlow'; +import createFlow from './internal/createFlow'; /** * This method is like `_.flow` except that it creates a function that @@ -6,9 +6,8 @@ import createFlow from '../internal/createFlow'; * * @static * @memberOf _ - * @alias backflow, compose - * @category Function - * @param {...Function} [funcs] Functions to invoke. + * @category Util + * @param {...(Function|Function[])} [funcs] Functions to invoke. * @returns {Function} Returns the new function. * @example * diff --git a/forEach.js b/forEach.js new file mode 100644 index 000000000..e8bd1f136 --- /dev/null +++ b/forEach.js @@ -0,0 +1,40 @@ +import arrayEach from './internal/arrayEach'; +import baseEach from './internal/baseEach'; +import isArray from './isArray'; +import toFunction from './internal/toFunction'; + +/** + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" property + * are iterated like arrays. To avoid this behavior use `_.forIn` or `_.forOwn` + * for object iteration. + * + * @static + * @memberOf _ + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @example + * + * _([1, 2]).forEach(function(value) { + * console.log(value); + * }); + * // => logs `1` then `2` + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => logs 'a' then 'b' (iteration order is not guaranteed) + */ +function forEach(collection, iteratee) { + return (typeof iteratee == 'function' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, toFunction(iteratee)); +} + +export default forEach; diff --git a/forEachRight.js b/forEachRight.js new file mode 100644 index 000000000..7cc4270c8 --- /dev/null +++ b/forEachRight.js @@ -0,0 +1,30 @@ +import arrayEachRight from './internal/arrayEachRight'; +import baseEachRight from './internal/baseEachRight'; +import isArray from './isArray'; +import toFunction from './internal/toFunction'; + +/** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => logs `2` then `1` + */ +function forEachRight(collection, iteratee) { + return (typeof iteratee == 'function' && isArray(collection)) + ? arrayEachRight(collection, iteratee) + : baseEachRight(collection, toFunction(iteratee)); +} + +export default forEachRight; diff --git a/object/forIn.js b/forIn.js similarity index 50% rename from object/forIn.js rename to forIn.js index 4ac5fdfe3..28551a061 100644 --- a/object/forIn.js +++ b/forIn.js @@ -1,18 +1,18 @@ -import baseFor from '../internal/baseFor'; -import createForIn from '../internal/createForIn'; +import baseFor from './internal/baseFor'; +import keysIn from './keysIn'; +import toFunction from './internal/toFunction'; /** * 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). Iteratee functions may exit - * iteration early by explicitly returning `false`. + * `iteratee` for each property. The iteratee is invoked with three arguments: + * (value, key, object). Iteratee functions may exit iteration early by explicitly + * returning `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -26,8 +26,10 @@ import createForIn from '../internal/createForIn'; * _.forIn(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed) + * // => logs 'a', 'b', then 'c' (iteration order is not guaranteed) */ -var forIn = createForIn(baseFor); +function forIn(object, iteratee) { + return object == null ? object : baseFor(object, toFunction(iteratee), keysIn); +} export default forIn; diff --git a/object/forInRight.js b/forInRight.js similarity index 62% rename from object/forInRight.js rename to forInRight.js index f9d368342..14e88c04a 100644 --- a/object/forInRight.js +++ b/forInRight.js @@ -1,5 +1,6 @@ -import baseForRight from '../internal/baseForRight'; -import createForIn from '../internal/createForIn'; +import baseForRight from './internal/baseForRight'; +import keysIn from './keysIn'; +import toFunction from './internal/toFunction'; /** * This method is like `_.forIn` except that it iterates over properties of @@ -10,7 +11,6 @@ import createForIn from '../internal/createForIn'; * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -24,8 +24,10 @@ import createForIn from '../internal/createForIn'; * _.forInRight(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c' + * // => logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c' */ -var forInRight = createForIn(baseForRight); +function forInRight(object, iteratee) { + return object == null ? object : baseForRight(object, toFunction(iteratee), keysIn); +} export default forInRight; diff --git a/object/forOwn.js b/forOwn.js similarity index 52% rename from object/forOwn.js rename to forOwn.js index 096b25ee9..f667ea2d1 100644 --- a/object/forOwn.js +++ b/forOwn.js @@ -1,18 +1,17 @@ -import baseForOwn from '../internal/baseForOwn'; -import createForOwn from '../internal/createForOwn'; +import baseForOwn from './internal/baseForOwn'; +import toFunction from './internal/toFunction'; /** * 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). Iteratee functions may exit iteration - * early by explicitly returning `false`. + * for each property. The iteratee is invoked with three arguments: + * (value, key, object). Iteratee functions may exit iteration early by + * explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -26,8 +25,10 @@ import createForOwn from '../internal/createForOwn'; * _.forOwn(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'a' and 'b' (iteration order is not guaranteed) + * // => logs 'a' then 'b' (iteration order is not guaranteed) */ -var forOwn = createForOwn(baseForOwn); +function forOwn(object, iteratee) { + return object && baseForOwn(object, toFunction(iteratee)); +} export default forOwn; diff --git a/object/forOwnRight.js b/forOwnRight.js similarity index 66% rename from object/forOwnRight.js rename to forOwnRight.js index 8d05a6948..58fc38cf9 100644 --- a/object/forOwnRight.js +++ b/forOwnRight.js @@ -1,5 +1,5 @@ -import baseForOwnRight from '../internal/baseForOwnRight'; -import createForOwn from '../internal/createForOwn'; +import baseForOwnRight from './internal/baseForOwnRight'; +import toFunction from './internal/toFunction'; /** * This method is like `_.forOwn` except that it iterates over properties of @@ -10,7 +10,6 @@ import createForOwn from '../internal/createForOwn'; * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * @@ -24,8 +23,10 @@ import createForOwn from '../internal/createForOwn'; * _.forOwnRight(new Foo, function(value, key) { * console.log(key); * }); - * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b' + * // => logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b' */ -var forOwnRight = createForOwn(baseForOwnRight); +function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, toFunction(iteratee)); +} export default forOwnRight; diff --git a/fromPairs.js b/fromPairs.js new file mode 100644 index 000000000..86bb0da1f --- /dev/null +++ b/fromPairs.js @@ -0,0 +1,29 @@ +import baseSet from './internal/baseSet'; + +/** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['fred', 30], ['barney', 40]]); + * // => { 'fred': 30, 'barney': 40 } + */ +function fromPairs(pairs) { + var index = -1, + length = pairs ? pairs.length : 0, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + baseSet(result, pair[0], pair[1]); + } + return result; +} + +export default fromPairs; diff --git a/function.default.js b/function.default.js new file mode 100644 index 000000000..34fe1ffa8 --- /dev/null +++ b/function.default.js @@ -0,0 +1,31 @@ +import after from './after'; +import ary from './ary'; +import before from './before'; +import bind from './bind'; +import bindKey from './bindKey'; +import curry from './curry'; +import curryRight from './curryRight'; +import debounce from './debounce'; +import defer from './defer'; +import delay from './delay'; +import flip from './flip'; +import memoize from './memoize'; +import negate from './negate'; +import once from './once'; +import overArgs from './overArgs'; +import partial from './partial'; +import partialRight from './partialRight'; +import rearg from './rearg'; +import rest from './rest'; +import spread from './spread'; +import throttle from './throttle'; +import unary from './unary'; +import wrap from './wrap'; + +export default { + after, ary, before, bind, bindKey, + curry, curryRight, debounce, defer, delay, + flip, memoize, negate, once, overArgs, + partial, partialRight, rearg, rest, spread, + throttle, unary, wrap +}; diff --git a/function.js b/function.js index f0de61d6a..7e3fc192c 100644 --- a/function.js +++ b/function.js @@ -1,55 +1,24 @@ -import after from './function/after'; -import ary from './function/ary'; -import backflow from './function/backflow'; -import before from './function/before'; -import bind from './function/bind'; -import bindAll from './function/bindAll'; -import bindKey from './function/bindKey'; -import compose from './function/compose'; -import curry from './function/curry'; -import curryRight from './function/curryRight'; -import debounce from './function/debounce'; -import defer from './function/defer'; -import delay from './function/delay'; -import flow from './function/flow'; -import flowRight from './function/flowRight'; -import memoize from './function/memoize'; -import modArgs from './function/modArgs'; -import negate from './function/negate'; -import once from './function/once'; -import partial from './function/partial'; -import partialRight from './function/partialRight'; -import rearg from './function/rearg'; -import restParam from './function/restParam'; -import spread from './function/spread'; -import throttle from './function/throttle'; -import wrap from './function/wrap'; - -export default { - 'after': after, - 'ary': ary, - 'backflow': backflow, - 'before': before, - 'bind': bind, - 'bindAll': bindAll, - 'bindKey': bindKey, - 'compose': compose, - 'curry': curry, - 'curryRight': curryRight, - 'debounce': debounce, - 'defer': defer, - 'delay': delay, - 'flow': flow, - 'flowRight': flowRight, - 'memoize': memoize, - 'modArgs': modArgs, - 'negate': negate, - 'once': once, - 'partial': partial, - 'partialRight': partialRight, - 'rearg': rearg, - 'restParam': restParam, - 'spread': spread, - 'throttle': throttle, - 'wrap': wrap -}; +export { default as after } from './after'; +export { default as ary } from './ary'; +export { default as before } from './before'; +export { default as bind } from './bind'; +export { default as bindKey } from './bindKey'; +export { default as curry } from './curry'; +export { default as curryRight } from './curryRight'; +export { default as debounce } from './debounce'; +export { default as defer } from './defer'; +export { default as delay } from './delay'; +export { default as flip } from './flip'; +export { default as memoize } from './memoize'; +export { default as negate } from './negate'; +export { default as once } from './once'; +export { default as overArgs } from './overArgs'; +export { default as partial } from './partial'; +export { default as partialRight } from './partialRight'; +export { default as rearg } from './rearg'; +export { default as rest } from './rest'; +export { default as spread } from './spread'; +export { default as throttle } from './throttle'; +export { default as unary } from './unary'; +export { default as wrap } from './wrap'; +export { default as default } from './function.default'; diff --git a/function/backflow.js b/function/backflow.js deleted file mode 100644 index 69295194f..000000000 --- a/function/backflow.js +++ /dev/null @@ -1,2 +0,0 @@ -import flowRight from './flowRight' -export default flowRight; diff --git a/function/bindAll.js b/function/bindAll.js deleted file mode 100644 index 2346f6349..000000000 --- a/function/bindAll.js +++ /dev/null @@ -1,50 +0,0 @@ -import baseFlatten from '../internal/baseFlatten'; -import createWrapper from '../internal/createWrapper'; -import functions from '../object/functions'; -import restParam from './restParam'; - -/** Used to compose bitmasks for wrapper metadata. */ -var BIND_FLAG = 1; - -/** - * Binds methods of an object to the object itself, overwriting the existing - * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all enumerable function - * properties, own and inherited, of `object` are bound. - * - * **Note:** This method does not set the "length" property of bound functions. - * - * @static - * @memberOf _ - * @category Function - * @param {Object} object The object to bind and assign the bound methods to. - * @param {...(string|string[])} [methodNames] The object method names to bind, - * specified as individual method names or arrays of method names. - * @returns {Object} Returns `object`. - * @example - * - * var view = { - * 'label': 'docs', - * 'onClick': function() { - * console.log('clicked ' + this.label); - * } - * }; - * - * _.bindAll(view); - * jQuery('#docs').on('click', view.onClick); - * // => logs 'clicked docs' when the element is clicked - */ -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; -}); - -export default bindAll; diff --git a/function/compose.js b/function/compose.js deleted file mode 100644 index 69295194f..000000000 --- a/function/compose.js +++ /dev/null @@ -1,2 +0,0 @@ -import flowRight from './flowRight' -export default flowRight; diff --git a/function/curry.js b/function/curry.js deleted file mode 100644 index fd170a5ff..000000000 --- a/function/curry.js +++ /dev/null @@ -1,51 +0,0 @@ -import createCurry from '../internal/createCurry'; - -/** Used to compose bitmasks for wrapper metadata. */ -var CURRY_FLAG = 8; - -/** - * Creates a function that accepts one or more arguments of `func` that when - * called either invokes `func` returning its result, if all `func` arguments - * have been provided, or returns a function that accepts one or more of the - * remaining `func` arguments, and so on. The arity of `func` may be specified - * if `func.length` is not sufficient. - * - * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, - * may be used as a placeholder for provided arguments. - * - * **Note:** This method does not set the "length" property of curried functions. - * - * @static - * @memberOf _ - * @category Function - * @param {Function} func The function to curry. - * @param {number} [arity=func.length] The arity of `func`. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {Function} Returns the new curried function. - * @example - * - * var abc = function(a, b, c) { - * return [a, b, c]; - * }; - * - * var curried = _.curry(abc); - * - * curried(1)(2)(3); - * // => [1, 2, 3] - * - * curried(1, 2)(3); - * // => [1, 2, 3] - * - * curried(1, 2, 3); - * // => [1, 2, 3] - * - * // using placeholders - * curried(1)(_, 3)(2); - * // => [1, 2, 3] - */ -var curry = createCurry(CURRY_FLAG); - -// Assign default placeholders. -curry.placeholder = {}; - -export default curry; diff --git a/function/modArgs.js b/function/modArgs.js deleted file mode 100644 index d52a58596..000000000 --- a/function/modArgs.js +++ /dev/null @@ -1,58 +0,0 @@ -import arrayEvery from '../internal/arrayEvery'; -import baseFlatten from '../internal/baseFlatten'; -import baseIsFunction from '../internal/baseIsFunction'; -import restParam from './restParam'; - -/** 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 nativeMin = Math.min; - -/** - * Creates a function that runs each argument through a corresponding - * transform function. - * - * @static - * @memberOf _ - * @category Function - * @param {Function} func The function to wrap. - * @param {...(Function|Function[])} [transforms] The functions to transform - * arguments, specified as individual functions or arrays of functions. - * @returns {Function} Returns the new function. - * @example - * - * function doubled(n) { - * return n * 2; - * } - * - * function square(n) { - * return n * n; - * } - * - * var modded = _.modArgs(function(x, y) { - * return [x, y]; - * }, square, doubled); - * - * modded(1, 2); - * // => [1, 4] - * - * modded(5, 10); - * // => [25, 20] - */ -var modArgs = restParam(function(func, transforms) { - transforms = baseFlatten(transforms); - if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) { - throw new TypeError(FUNC_ERROR_TEXT); - } - var length = transforms.length; - return restParam(function(args) { - var index = nativeMin(args.length, length); - while (index--) { - args[index] = transforms[index](args[index]); - } - return func.apply(this, args); - }); -}); - -export default modArgs; diff --git a/functions.js b/functions.js new file mode 100644 index 000000000..dd76adcde --- /dev/null +++ b/functions.js @@ -0,0 +1,29 @@ +import baseFunctions from './internal/baseFunctions'; +import keys from './keys'; + +/** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of property names. + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ +function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); +} + +export default functions; diff --git a/functionsIn.js b/functionsIn.js new file mode 100644 index 000000000..f88c57e95 --- /dev/null +++ b/functionsIn.js @@ -0,0 +1,29 @@ +import baseFunctions from './internal/baseFunctions'; +import keysIn from './keysIn'; + +/** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of property names. + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ +function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); +} + +export default functionsIn; diff --git a/object/get.js b/get.js similarity index 73% rename from object/get.js rename to get.js index de9489008..6a863a557 100644 --- a/object/get.js +++ b/get.js @@ -1,8 +1,7 @@ -import baseGet from '../internal/baseGet'; -import toPath from '../internal/toPath'; +import baseGet from './internal/baseGet'; /** - * Gets the property value at `path` of `object`. If the resolved value is + * Gets the value at `path` of `object`. If the resolved value is * `undefined` the `defaultValue` is used in its place. * * @static @@ -26,7 +25,7 @@ import toPath from '../internal/toPath'; * // => 'default' */ function get(object, path, defaultValue) { - var result = object == null ? undefined : baseGet(object, toPath(path), (path + '')); + var result = object == null ? undefined : baseGet(object, path); return result === undefined ? defaultValue : result; } diff --git a/groupBy.js b/groupBy.js new file mode 100644 index 000000000..b7e03d3da --- /dev/null +++ b/groupBy.js @@ -0,0 +1,38 @@ +import createAggregator from './internal/createAggregator'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +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 invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // using the `_.property` iteratee shorthand + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ +var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [value]; + } +}); + +export default groupBy; diff --git a/lang/gt.js b/gt.js similarity index 100% rename from lang/gt.js rename to gt.js diff --git a/lang/gte.js b/gte.js similarity index 100% rename from lang/gte.js rename to gte.js diff --git a/has.js b/has.js new file mode 100644 index 000000000..438179059 --- /dev/null +++ b/has.js @@ -0,0 +1,34 @@ +import baseHas from './internal/baseHas'; +import hasPath from './internal/hasPath'; + +/** + * Checks if `path` is a direct property of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': { 'c': 3 } } }; + * var other = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b.c'); + * // => true + * + * _.has(object, ['a', 'b', 'c']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ +function has(object, path) { + return hasPath(object, path, baseHas); +} + +export default has; diff --git a/hasIn.js b/hasIn.js new file mode 100644 index 000000000..a700e43d6 --- /dev/null +++ b/hasIn.js @@ -0,0 +1,33 @@ +import baseHasIn from './internal/baseHasIn'; +import hasPath from './internal/hasPath'; + +/** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b.c'); + * // => true + * + * _.hasIn(object, ['a', 'b', 'c']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ +function hasIn(object, path) { + return hasPath(object, path, baseHasIn); +} + +export default hasIn; diff --git a/array/first.js b/head.js similarity index 73% rename from array/first.js rename to head.js index e5f259842..5ae4f6364 100644 --- a/array/first.js +++ b/head.js @@ -3,20 +3,20 @@ * * @static * @memberOf _ - * @alias head + * @alias first * @category Array * @param {Array} array The array to query. * @returns {*} Returns the first element of `array`. * @example * - * _.first([1, 2, 3]); + * _.head([1, 2, 3]); * // => 1 * - * _.first([]); + * _.head([]); * // => undefined */ -function first(array) { +function head(array) { return array ? array[0] : undefined; } -export default first; +export default head; diff --git a/utility/identity.js b/identity.js similarity index 94% rename from utility/identity.js rename to identity.js index 0c9c17de3..c6101d9d7 100644 --- a/utility/identity.js +++ b/identity.js @@ -3,7 +3,7 @@ * * @static * @memberOf _ - * @category Utility + * @category Util * @param {*} value Any value. * @returns {*} Returns `value`. * @example diff --git a/number/inRange.js b/inRange.js similarity index 55% rename from number/inRange.js rename to inRange.js index 1db32d688..face7d88c 100644 --- a/number/inRange.js +++ b/inRange.js @@ -1,18 +1,19 @@ -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max, - nativeMin = Math.min; +import baseInRange from './internal/baseInRange'; +import toNumber from './toNumber'; /** * Checks if `n` is between `start` and up to but not including, `end`. If * `end` is not specified it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. * * @static * @memberOf _ * @category Number - * @param {number} n The number to check. + * @param {number} number The number to check. * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. - * @returns {boolean} Returns `true` if `n` is in the range, else `false`. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. * @example * * _.inRange(3, 2, 4); @@ -32,16 +33,20 @@ var nativeMax = Math.max, * * _.inRange(5.2, 4); * // => false + * + * _.inRange(-3, -2, -6); + * // => true */ -function inRange(value, start, end) { - start = +start || 0; +function inRange(number, start, end) { + start = toNumber(start) || 0; if (end === undefined) { end = start; start = 0; } else { - end = +end || 0; + end = toNumber(end) || 0; } - return value >= nativeMin(start, end) && value < nativeMax(start, end); + number = toNumber(number); + return baseInRange(number, start, end); } export default inRange; diff --git a/includes.js b/includes.js new file mode 100644 index 000000000..a7f03cdd9 --- /dev/null +++ b/includes.js @@ -0,0 +1,51 @@ +import baseIndexOf from './internal/baseIndexOf'; +import isArrayLike from './isArrayLike'; +import isString from './isString'; +import toInteger from './toInteger'; +import values from './values'; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Checks if `value` is in `collection`. If `collection` is a string it's checked + * for a substring of `value`, otherwise [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); + * // => true + * + * _.includes('pebbles', 'eb'); + * // => true + */ +function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); +} + +export default includes; diff --git a/array/indexOf.js b/indexOf.js similarity index 53% rename from array/indexOf.js rename to indexOf.js index dad65c144..25126230b 100644 --- a/array/indexOf.js +++ b/indexOf.js @@ -1,7 +1,7 @@ -import baseIndexOf from '../internal/baseIndexOf'; -import binaryIndex from '../internal/binaryIndex'; +import baseIndexOf from './internal/baseIndexOf'; +import toInteger from './toInteger'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; /** @@ -16,8 +16,7 @@ var nativeMax = Math.max; * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. - * @param {boolean|number} [fromIndex=0] The index to search from or `true` - * to perform a binary search on a sorted array. + * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. * @example * @@ -27,27 +26,17 @@ var nativeMax = Math.max; * // using `fromIndex` * _.indexOf([1, 2, 1, 2], 2, 2); * // => 3 - * - * // performing a binary search - * _.indexOf([1, 1, 2, 2], 2, true); - * // => 2 */ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (!length) { return -1; } - if (typeof fromIndex == 'number') { - fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; - } else if (fromIndex) { - var index = binaryIndex(array, value); - if (index < length && - (value === value ? (value === array[index]) : (array[index] !== array[index]))) { - return index; - } - return -1; + fromIndex = toInteger(fromIndex); + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); } - return baseIndexOf(array, value, fromIndex || 0); + return baseIndexOf(array, value, fromIndex); } export default indexOf; diff --git a/array/initial.js b/initial.js similarity index 100% rename from array/initial.js rename to initial.js diff --git a/internal/Hash.js b/internal/Hash.js new file mode 100644 index 000000000..0fba9376c --- /dev/null +++ b/internal/Hash.js @@ -0,0 +1,17 @@ +import nativeCreate from './nativeCreate'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Creates an hash object. + * + * @private + * @returns {Object} Returns the new hash object. + */ +function Hash() {} + +// Avoid inheriting from `Object.prototype` when possible. +Hash.prototype = nativeCreate ? nativeCreate(null) : objectProto; + +export default Hash; diff --git a/internal/LazyWrapper.js b/internal/LazyWrapper.js index 4c8e5b420..e93e4a1ec 100644 --- a/internal/LazyWrapper.js +++ b/internal/LazyWrapper.js @@ -1,8 +1,8 @@ import baseCreate from './baseCreate'; import baseLodash from './baseLodash'; -/** Used as references for `-Infinity` and `Infinity`. */ -var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295; /** * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. @@ -16,7 +16,7 @@ function LazyWrapper(value) { this.__dir__ = 1; this.__filtered__ = false; this.__iteratees__ = []; - this.__takeCount__ = POSITIVE_INFINITY; + this.__takeCount__ = MAX_ARRAY_LENGTH; this.__views__ = []; } diff --git a/internal/LodashWrapper.js b/internal/LodashWrapper.js index adfc689c3..08a1cdd4a 100644 --- a/internal/LodashWrapper.js +++ b/internal/LodashWrapper.js @@ -7,12 +7,13 @@ import baseLodash from './baseLodash'; * @private * @param {*} value The value to wrap. * @param {boolean} [chainAll] Enable chaining for all wrapper methods. - * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. */ -function LodashWrapper(value, chainAll, actions) { +function LodashWrapper(value, chainAll) { this.__wrapped__ = value; - this.__actions__ = actions || []; + this.__actions__ = []; this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; } LodashWrapper.prototype = baseCreate(baseLodash.prototype); diff --git a/internal/Map.js b/internal/Map.js new file mode 100644 index 000000000..846355c16 --- /dev/null +++ b/internal/Map.js @@ -0,0 +1,7 @@ +import getNative from './getNative'; +import root from './root'; + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +export default Map; diff --git a/internal/MapCache.js b/internal/MapCache.js index d4a55adf9..13ee61db3 100644 --- a/internal/MapCache.js +++ b/internal/MapCache.js @@ -1,21 +1,28 @@ +import mapClear from './mapClear'; import mapDelete from './mapDelete'; import mapGet from './mapGet'; import mapHas from './mapHas'; import mapSet from './mapSet'; /** - * Creates a cache object to store key/value pairs. + * Creates a map cache object to store key-value pairs. * * @private - * @static - * @name Cache - * @memberOf _.memoize + * @param {Array} [values] The values to cache. */ -function MapCache() { - this.__data__ = {}; +function MapCache(values) { + var index = -1, + length = values ? values.length : 0; + + this.clear(); + while (++index < length) { + var entry = values[index]; + this.set(entry[0], entry[1]); + } } -// Add functions to the `Map` cache. +// Add functions to the `MapCache`. +MapCache.prototype.clear = mapClear; MapCache.prototype['delete'] = mapDelete; MapCache.prototype.get = mapGet; MapCache.prototype.has = mapHas; diff --git a/internal/Reflect.js b/internal/Reflect.js new file mode 100644 index 000000000..89162b591 --- /dev/null +++ b/internal/Reflect.js @@ -0,0 +1,6 @@ +import root from './root'; + +/** Built-in value references. */ +var Reflect = root.Reflect; + +export default Reflect; diff --git a/internal/Set.js b/internal/Set.js new file mode 100644 index 000000000..23a328016 --- /dev/null +++ b/internal/Set.js @@ -0,0 +1,7 @@ +import getNative from './getNative'; +import root from './root'; + +/* Built-in method references that are verified to be native. */ +var Set = getNative(root, 'Set'); + +export default Set; diff --git a/internal/SetCache.js b/internal/SetCache.js index 016612116..eca84426f 100644 --- a/internal/SetCache.js +++ b/internal/SetCache.js @@ -1,30 +1,24 @@ +import MapCache from './MapCache'; import cachePush from './cachePush'; -import getNative from './getNative'; -import root from './root'; - -/** Native method references. */ -var Set = getNative(root, 'Set'); - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeCreate = getNative(Object, 'create'); /** * - * Creates a cache object to store unique values. + * Creates a set cache object to store unique values. * * @private * @param {Array} [values] The values to cache. */ function SetCache(values) { - var length = values ? values.length : 0; + var index = -1, + length = values ? values.length : 0; - this.data = { 'hash': nativeCreate(null), 'set': new Set }; - while (length--) { - this.push(values[length]); + this.__data__ = new MapCache; + while (++index < length) { + this.push(values[index]); } } -// Add functions to the `Set` cache. +// Add functions to the `SetCache`. SetCache.prototype.push = cachePush; export default SetCache; diff --git a/internal/Stack.js b/internal/Stack.js new file mode 100644 index 000000000..821153dc3 --- /dev/null +++ b/internal/Stack.js @@ -0,0 +1,31 @@ +import stackClear from './stackClear'; +import stackDelete from './stackDelete'; +import stackGet from './stackGet'; +import stackHas from './stackHas'; +import stackSet from './stackSet'; + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @param {Array} [values] The values to cache. + */ +function Stack(values) { + var index = -1, + length = values ? values.length : 0; + + this.clear(); + while (++index < length) { + var entry = values[index]; + this.set(entry[0], entry[1]); + } +} + +// Add functions to the `Stack` cache. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +export default Stack; diff --git a/internal/Uint8Array.js b/internal/Uint8Array.js new file mode 100644 index 000000000..cabbb800d --- /dev/null +++ b/internal/Uint8Array.js @@ -0,0 +1,6 @@ +import root from './root'; + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +export default Uint8Array; diff --git a/internal/WeakMap.js b/internal/WeakMap.js new file mode 100644 index 000000000..e0410c589 --- /dev/null +++ b/internal/WeakMap.js @@ -0,0 +1,7 @@ +import getNative from './getNative'; +import root from './root'; + +/* Built-in method references that are verified to be native. */ +var WeakMap = getNative(root, 'WeakMap'); + +export default WeakMap; diff --git a/internal/_Symbol.js b/internal/_Symbol.js new file mode 100644 index 000000000..bffed6a80 --- /dev/null +++ b/internal/_Symbol.js @@ -0,0 +1,6 @@ +import root from './root'; + +/** Built-in value references. */ +var _Symbol = root.Symbol; + +export default _Symbol; diff --git a/internal/addMapEntry.js b/internal/addMapEntry.js new file mode 100644 index 000000000..486c184ff --- /dev/null +++ b/internal/addMapEntry.js @@ -0,0 +1,14 @@ +/** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ +function addMapEntry(map, pair) { + map.set(pair[0], pair[1]); + return map; +} + +export default addMapEntry; diff --git a/internal/addSetEntry.js b/internal/addSetEntry.js new file mode 100644 index 000000000..a999aed9c --- /dev/null +++ b/internal/addSetEntry.js @@ -0,0 +1,14 @@ +/** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ +function addSetEntry(set, value) { + set.add(value); + return set; +} + +export default addSetEntry; diff --git a/internal/apply.js b/internal/apply.js new file mode 100644 index 000000000..28994b185 --- /dev/null +++ b/internal/apply.js @@ -0,0 +1,22 @@ +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + var length = args ? args.length : 0; + switch (length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +export default apply; diff --git a/internal/arrayConcat.js b/internal/arrayConcat.js index 9d5e23dd4..61a7df31c 100644 --- a/internal/arrayConcat.js +++ b/internal/arrayConcat.js @@ -1,9 +1,9 @@ /** - * Creates a new array joining `array` with `other`. + * Creates a new array concatenating `array` with `other`. * * @private - * @param {Array} array The array to join. - * @param {Array} other The other array to join. + * @param {Array} array The first array to concatenate. + * @param {Array} other The second array to concatenate. * @returns {Array} Returns the new concatenated array. */ function arrayConcat(array, other) { diff --git a/internal/arrayEach.js b/internal/arrayEach.js index 7bf245dca..142993ecd 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 and `this` binding. + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayEachRight.js b/internal/arrayEachRight.js index 8d39f733c..d39a69a94 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 and `this` binding. + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayEvery.js b/internal/arrayEvery.js index 92da7c0d6..dcf4460ef 100644 --- a/internal/arrayEvery.js +++ b/internal/arrayEvery.js @@ -1,12 +1,11 @@ /** - * A specialized version of `_.every` for arrays without support for callback - * shorthands and `this` binding. + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if all elements pass the predicate check, - * else `false`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`. */ function arrayEvery(array, predicate) { var index = -1, diff --git a/internal/arrayExtremum.js b/internal/arrayExtremum.js deleted file mode 100644 index 1c77ac368..000000000 --- a/internal/arrayExtremum.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * A specialized version of `baseExtremum` for arrays which invokes `iteratee` - * with one argument: (value). - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {Function} comparator The function used to compare values. - * @param {*} exValue The initial extremum value. - * @returns {*} Returns the extremum value. - */ -function arrayExtremum(array, iteratee, comparator, exValue) { - var index = -1, - length = array.length, - computed = exValue, - result = computed; - - while (++index < length) { - var value = array[index], - current = +iteratee(value); - - if (comparator(current, computed)) { - computed = current; - result = value; - } - } - return result; -} - -export default arrayExtremum; diff --git a/internal/arrayFilter.js b/internal/arrayFilter.js index d9ae85782..247b29891 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 and `this` binding. + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayIncludes.js b/internal/arrayIncludes.js new file mode 100644 index 000000000..9a99b17ce --- /dev/null +++ b/internal/arrayIncludes.js @@ -0,0 +1,16 @@ +import baseIndexOf from './baseIndexOf'; + +/** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} array The array to search. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludes(array, value) { + return !!array.length && baseIndexOf(array, value, 0) > -1; +} + +export default arrayIncludes; diff --git a/internal/arrayIncludesWith.js b/internal/arrayIncludesWith.js new file mode 100644 index 000000000..b84117693 --- /dev/null +++ b/internal/arrayIncludesWith.js @@ -0,0 +1,23 @@ +/** + * A specialized version of `_.includesWith` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} array The array to search. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; +} + +export default arrayIncludesWith; diff --git a/internal/arrayMap.js b/internal/arrayMap.js index 59c3920b9..eb475cc15 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 and `this` binding. + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. * * @private * @param {Array} array The array to iterate over. diff --git a/internal/arrayReduce.js b/internal/arrayReduce.js index 5e2cc9ac0..25d17865c 100644 --- a/internal/arrayReduce.js +++ b/internal/arrayReduce.js @@ -1,13 +1,12 @@ /** - * A specialized version of `_.reduce` for arrays without support for callback - * shorthands and `this` binding. + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. - * @param {boolean} [initFromArray] Specify using the first element of `array` - * as the initial value. + * @param {boolean} [initFromArray] Specify using the first element of `array` as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initFromArray) { diff --git a/internal/arrayReduceRight.js b/internal/arrayReduceRight.js index 98be5537a..f7549633b 100644 --- a/internal/arrayReduceRight.js +++ b/internal/arrayReduceRight.js @@ -1,13 +1,12 @@ /** * A specialized version of `_.reduceRight` for arrays without support for - * callback shorthands and `this` binding. + * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. - * @param {boolean} [initFromArray] Specify using the last element of `array` - * as the initial value. + * @param {boolean} [initFromArray] Specify using the last element of `array` as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduceRight(array, iteratee, accumulator, initFromArray) { diff --git a/internal/arraySome.js b/internal/arraySome.js index 48c767d9d..0e3f1850f 100644 --- a/internal/arraySome.js +++ b/internal/arraySome.js @@ -1,12 +1,11 @@ /** - * A specialized version of `_.some` for arrays without support for callback - * shorthands and `this` binding. + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. + * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`. */ function arraySome(array, predicate) { var index = -1, diff --git a/internal/arraySum.js b/internal/arraySum.js deleted file mode 100644 index 27ff80517..000000000 --- a/internal/arraySum.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * A specialized version of `_.sum` for arrays without support for callback - * shorthands and `this` binding.. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {number} Returns the sum. - */ -function arraySum(array, iteratee) { - var length = array.length, - result = 0; - - while (length--) { - result += +iteratee(array[length]) || 0; - } - return result; -} - -export default arraySum; diff --git a/internal/assignDefaults.js b/internal/assignDefaults.js deleted file mode 100644 index f91ee0b41..000000000 --- a/internal/assignDefaults.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Used by `_.defaults` to customize its `_.assign` use. - * - * @private - * @param {*} objectValue The destination object property value. - * @param {*} sourceValue The source object property value. - * @returns {*} Returns the value to assign to the destination object. - */ -function assignDefaults(objectValue, sourceValue) { - return objectValue === undefined ? sourceValue : objectValue; -} - -export default assignDefaults; diff --git a/internal/assignInDefaults.js b/internal/assignInDefaults.js new file mode 100644 index 000000000..b3af762e7 --- /dev/null +++ b/internal/assignInDefaults.js @@ -0,0 +1,27 @@ +import eq from '../eq'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used by `_.defaults` to customize its `_.assignIn` use. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ +function assignInDefaults(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; +} + +export default assignInDefaults; diff --git a/internal/assignMergeValue.js b/internal/assignMergeValue.js new file mode 100644 index 000000000..56486df21 --- /dev/null +++ b/internal/assignMergeValue.js @@ -0,0 +1,18 @@ +import eq from '../eq'; + +/** + * This function is like `assignValue` except that it doesn't assign `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (typeof key == 'number' && value === undefined && !(key in object))) { + object[key] = value; + } +} + +export default assignMergeValue; diff --git a/internal/assignOwnDefaults.js b/internal/assignOwnDefaults.js deleted file mode 100644 index 5cd1af27f..000000000 --- a/internal/assignOwnDefaults.js +++ /dev/null @@ -1,26 +0,0 @@ -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Used by `_.template` to customize its `_.assign` use. - * - * **Note:** This function is like `assignDefaults` except that it ignores - * inherited property values when checking if a property is `undefined`. - * - * @private - * @param {*} objectValue The destination object property value. - * @param {*} sourceValue The source object property value. - * @param {string} key The key associated with the object and source values. - * @param {Object} object The destination object. - * @returns {*} Returns the value to assign to the destination object. - */ -function assignOwnDefaults(objectValue, sourceValue, key, object) { - return (objectValue === undefined || !hasOwnProperty.call(object, key)) - ? sourceValue - : objectValue; -} - -export default assignOwnDefaults; diff --git a/internal/assignValue.js b/internal/assignValue.js new file mode 100644 index 000000000..b7d2b3e52 --- /dev/null +++ b/internal/assignValue.js @@ -0,0 +1,28 @@ +import eq from '../eq'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if ((!eq(objValue, value) || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) || + (value === undefined && !(key in object))) { + object[key] = value; + } +} + +export default assignValue; diff --git a/internal/assignWith.js b/internal/assignWith.js deleted file mode 100644 index 9343e6f16..000000000 --- a/internal/assignWith.js +++ /dev/null @@ -1,32 +0,0 @@ -import keys from '../object/keys'; - -/** - * A specialized version of `_.assign` for customizing assigned values without - * support for argument juggling, multiple sources, and `this` binding `customizer` - * functions. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {Function} customizer The function to customize assigned values. - * @returns {Object} Returns `object`. - */ -function assignWith(object, source, customizer) { - var index = -1, - props = keys(source), - length = props.length; - - while (++index < length) { - var key = props[index], - value = object[key], - result = customizer(value, source[key], key, object, source); - - if ((result === result ? (result !== value) : (value === value)) || - (value === undefined && !(key in object))) { - object[key] = result; - } - } - return object; -} - -export default assignWith; diff --git a/internal/assocDelete.js b/internal/assocDelete.js new file mode 100644 index 000000000..206d7d8e9 --- /dev/null +++ b/internal/assocDelete.js @@ -0,0 +1,31 @@ +import assocIndexOf from './assocIndexOf'; + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the associative array. + * + * @private + * @param {Array} array The array to query. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function assocDelete(array, key) { + var index = assocIndexOf(array, key); + if (index < 0) { + return false; + } + var lastIndex = array.length - 1; + if (index == lastIndex) { + array.pop(); + } else { + splice.call(array, index, 1); + } + return true; +} + +export default assocDelete; diff --git a/internal/assocGet.js b/internal/assocGet.js new file mode 100644 index 000000000..a171e8486 --- /dev/null +++ b/internal/assocGet.js @@ -0,0 +1,16 @@ +import assocIndexOf from './assocIndexOf'; + +/** + * Gets the associative array value for `key`. + * + * @private + * @param {Array} array The array to query. + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function assocGet(array, key) { + var index = assocIndexOf(array, key); + return index < 0 ? undefined : array[index][1]; +} + +export default assocGet; diff --git a/internal/assocHas.js b/internal/assocHas.js new file mode 100644 index 000000000..9691dbc2c --- /dev/null +++ b/internal/assocHas.js @@ -0,0 +1,15 @@ +import assocIndexOf from './assocIndexOf'; + +/** + * Checks if an associative array value for `key` exists. + * + * @private + * @param {Array} array The array to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function assocHas(array, key) { + return assocIndexOf(array, key) > -1; +} + +export default assocHas; diff --git a/internal/assocIndexOf.js b/internal/assocIndexOf.js new file mode 100644 index 000000000..969b9a8ec --- /dev/null +++ b/internal/assocIndexOf.js @@ -0,0 +1,22 @@ +import eq from '../eq'; + +/** + * Gets the index at which the first occurrence of `key` is found in `array` + * of key-value pairs. + * + * @private + * @param {Array} array The array to search. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +export default assocIndexOf; diff --git a/internal/assocSet.js b/internal/assocSet.js new file mode 100644 index 000000000..8adf34e99 --- /dev/null +++ b/internal/assocSet.js @@ -0,0 +1,20 @@ +import assocIndexOf from './assocIndexOf'; + +/** + * Sets the associative array `key` to `value`. + * + * @private + * @param {Array} array The array to modify. + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + */ +function assocSet(array, key, value) { + var index = assocIndexOf(array, key); + if (index < 0) { + array.push([key, value]); + } else { + array[index][1] = value; + } +} + +export default assocSet; diff --git a/internal/baseAssign.js b/internal/baseAssign.js index 98aa91b09..30097379f 100644 --- a/internal/baseAssign.js +++ b/internal/baseAssign.js @@ -1,9 +1,9 @@ -import baseCopy from './baseCopy'; -import keys from '../object/keys'; +import copyObject from './copyObject'; +import keys from '../keys'; /** - * The base implementation of `_.assign` without support for argument juggling, - * multiple sources, and `customizer` functions. + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. * * @private * @param {Object} object The destination object. @@ -11,9 +11,7 @@ import keys from '../object/keys'; * @returns {Object} Returns `object`. */ function baseAssign(object, source) { - return source == null - ? object - : baseCopy(source, keys(source), object); + return object && copyObject(source, keys(source), object); } export default baseAssign; diff --git a/internal/baseAt.js b/internal/baseAt.js index dcc302831..135ca2f04 100644 --- a/internal/baseAt.js +++ b/internal/baseAt.js @@ -1,30 +1,21 @@ -import isArrayLike from './isArrayLike'; -import isIndex from './isIndex'; +import get from '../get'; /** - * The base implementation of `_.at` without support for string collections - * and individual key arguments. + * The base implementation of `_.at` without support for individual paths. * * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {number[]|string[]} props The property names or indexes of elements to pick. + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths of elements to pick. * @returns {Array} Returns the new array of picked elements. */ -function baseAt(collection, props) { +function baseAt(object, paths) { var index = -1, - isNil = collection == null, - isArr = !isNil && isArrayLike(collection), - length = isArr ? collection.length : 0, - propsLength = props.length, - result = Array(propsLength); + isNil = object == null, + length = paths.length, + result = Array(length); - while(++index < propsLength) { - var key = props[index]; - if (isArr) { - result[index] = isIndex(key, length) ? collection[key] : undefined; - } else { - result[index] = isNil ? undefined : collection[key]; - } + while (++index < length) { + result[index] = isNil ? undefined : get(object, paths[index]); } return result; } diff --git a/internal/baseCallback.js b/internal/baseCallback.js deleted file mode 100644 index 1d05a5ffd..000000000 --- a/internal/baseCallback.js +++ /dev/null @@ -1,35 +0,0 @@ -import baseMatches from './baseMatches'; -import baseMatchesProperty from './baseMatchesProperty'; -import bindCallback from './bindCallback'; -import identity from '../utility/identity'; -import property from '../utility/property'; - -/** - * The base implementation of `_.callback` which supports specifying the - * number of arguments to provide to `func`. - * - * @private - * @param {*} [func=_.identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [argCount] The number of arguments to provide to `func`. - * @returns {Function} Returns the callback. - */ -function baseCallback(func, thisArg, argCount) { - var type = typeof func; - if (type == 'function') { - return thisArg === undefined - ? func - : bindCallback(func, thisArg, argCount); - } - if (func == null) { - return identity; - } - if (type == 'object') { - return baseMatches(func); - } - return thisArg === undefined - ? property(func) - : baseMatchesProperty(func, thisArg); -} - -export default baseCallback; diff --git a/internal/baseClamp.js b/internal/baseClamp.js new file mode 100644 index 000000000..bb05ec270 --- /dev/null +++ b/internal/baseClamp.js @@ -0,0 +1,22 @@ +/** + * The base implementation of `_.clamp` which doesn't coerce arguments to numbers. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ +function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; +} + +export default baseClamp; diff --git a/internal/baseClone.js b/internal/baseClone.js index 0679f34d5..bcc3299b2 100644 --- a/internal/baseClone.js +++ b/internal/baseClone.js @@ -1,12 +1,17 @@ -import arrayCopy from './arrayCopy'; +import Stack from './Stack'; import arrayEach from './arrayEach'; +import assignValue from './assignValue'; import baseAssign from './baseAssign'; import baseForOwn from './baseForOwn'; +import copyArray from './copyArray'; +import copySymbols from './copySymbols'; +import getTag from './getTag'; import initCloneArray from './initCloneArray'; import initCloneByTag from './initCloneByTag'; import initCloneObject from './initCloneObject'; -import isArray from '../lang/isArray'; -import isObject from '../lang/isObject'; +import isArray from '../isArray'; +import isHostObject from './isHostObject'; +import isObject from '../isObject'; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', @@ -15,12 +20,14 @@ var argsTag = '[object Arguments]', dateTag = '[object Date]', errorTag = '[object Error]', funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', mapTag = '[object Map]', numberTag = '[object Number]', objectTag = '[object Object]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', + symbolTag = '[object Symbol]', weakMapTag = '[object WeakMap]'; var arrayBufferTag = '[object ArrayBuffer]', @@ -41,41 +48,32 @@ cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = -cloneableTags[numberTag] = cloneableTags[objectTag] = -cloneableTags[regexpTag] = cloneableTags[stringTag] = -cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = -cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; +cloneableTags[mapTag] = cloneableTags[numberTag] = +cloneableTags[objectTag] = cloneableTags[regexpTag] = +cloneableTags[setTag] = cloneableTags[stringTag] = +cloneableTags[symbolTag] = cloneableTags[uint8Tag] = +cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = +cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = -cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; -/** Used for native method references. */ -var objectProto = Object.prototype; - /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ -var objToString = objectProto.toString; - -/** - * The base implementation of `_.clone` without support for argument juggling - * and `this` binding `customizer` functions. + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. - * @param {Function} [customizer] The function to customize cloning values. + * @param {Function} [customizer] The function to customize cloning. * @param {string} [key] The key of `value`. - * @param {Object} [object] The object `value` belongs to. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates clones with source counterparts. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. * @returns {*} Returns the cloned value. */ -function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { +function baseClone(value, isDeep, customizer, key, object, stack) { var result; if (customizer) { - result = object ? customizer(value, key, object) : customizer(value); + result = object ? customizer(value, key, object, stack) : customizer(value); } if (result !== undefined) { return result; @@ -87,16 +85,19 @@ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { if (isArr) { result = initCloneArray(value); if (!isDeep) { - return arrayCopy(value, result); + return copyArray(value, result); } } else { - var tag = objToString.call(value), - isFunc = tag == funcTag; + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + if (isHostObject(value)) { + return object ? value : {}; + } result = initCloneObject(isFunc ? {} : value); if (!isDeep) { - return baseAssign(result, value); + return copySymbols(value, baseAssign(result, value)); } } else { return cloneableTags[tag] @@ -105,24 +106,18 @@ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { } } // Check for circular references and return its corresponding clone. - stackA || (stackA = []); - stackB || (stackB = []); - - var length = stackA.length; - while (length--) { - if (stackA[length] == value) { - return stackB[length]; - } + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; } - // Add the source value to the stack of traversed objects and associate it with its clone. - stackA.push(value); - stackB.push(result); + stack.set(value, result); // Recursively populate clone (susceptible to call stack limits). (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { - result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + assignValue(result, key, baseClone(subValue, isDeep, customizer, key, value, stack)); }); - return result; + return isArr ? result : copySymbols(value, result); } export default baseClone; diff --git a/internal/baseCompareAscending.js b/internal/baseCompareAscending.js deleted file mode 100644 index 113811a1e..000000000 --- a/internal/baseCompareAscending.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The base implementation of `compareAscending` which compares values and - * sorts them in ascending order without guaranteeing a stable sort. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {number} Returns the sort order indicator for `value`. - */ -function baseCompareAscending(value, other) { - if (value !== other) { - var valIsNull = value === null, - valIsUndef = value === undefined, - valIsReflexive = value === value; - - var othIsNull = other === null, - othIsUndef = other === undefined, - othIsReflexive = other === other; - - if ((value > other && !othIsNull) || !valIsReflexive || - (valIsNull && !othIsUndef && othIsReflexive) || - (valIsUndef && othIsReflexive)) { - return 1; - } - if ((value < other && !valIsNull) || !othIsReflexive || - (othIsNull && !valIsUndef && valIsReflexive) || - (othIsUndef && valIsReflexive)) { - return -1; - } - } - return 0; -} - -export default baseCompareAscending; diff --git a/internal/baseConforms.js b/internal/baseConforms.js new file mode 100644 index 000000000..5560bb8cf --- /dev/null +++ b/internal/baseConforms.js @@ -0,0 +1,32 @@ +import keys from '../keys'; + +/** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new function. + */ +function baseConforms(source) { + var props = keys(source), + length = props.length; + + return function(object) { + if (object == null) { + return !length; + } + var index = length; + while (index--) { + var key = props[index], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in Object(object))) || !predicate(value)) { + return false; + } + } + return true; + }; +} + +export default baseConforms; diff --git a/internal/baseCreate.js b/internal/baseCreate.js index b95d4a016..4ea485da6 100644 --- a/internal/baseCreate.js +++ b/internal/baseCreate.js @@ -1,4 +1,4 @@ -import isObject from '../lang/isObject'; +import isObject from '../isObject'; /** * The base implementation of `_.create` without support for assigning diff --git a/internal/baseDelay.js b/internal/baseDelay.js index 19cde60f9..f674ec780 100644 --- a/internal/baseDelay.js +++ b/internal/baseDelay.js @@ -2,8 +2,8 @@ var FUNC_ERROR_TEXT = 'Expected a function'; /** - * The base implementation of `_.delay` and `_.defer` which accepts an index - * of where to slice the arguments to provide to `func`. + * The base implementation of `_.delay` and `_.defer` which accepts an array + * of `func` arguments. * * @private * @param {Function} func The function to delay. diff --git a/internal/baseDifference.js b/internal/baseDifference.js index 967360ef3..a2f73009e 100644 --- a/internal/baseDifference.js +++ b/internal/baseDifference.js @@ -1,51 +1,62 @@ -import baseIndexOf from './baseIndexOf'; -import cacheIndexOf from './cacheIndexOf'; -import createCache from './createCache'; +import SetCache from './SetCache'; +import arrayIncludes from './arrayIncludes'; +import arrayIncludesWith from './arrayIncludesWith'; +import arrayMap from './arrayMap'; +import baseUnary from './baseUnary'; +import cacheHas from './cacheHas'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** - * The base implementation of `_.difference` which accepts a single array - * of values to exclude. + * The base implementation of methods like `_.difference` without support for + * excluding multiple arrays or iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of filtered values. */ -function baseDifference(array, values) { - var length = array ? array.length : 0, - result = []; +function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; if (!length) { return result; } - var index = -1, - indexOf = baseIndexOf, - isCommon = true, - cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null, - valuesLength = values.length; - - if (cache) { - indexOf = cacheIndexOf; + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; isCommon = false; - values = cache; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); } outer: while (++index < length) { - var value = array[index]; + var value = array[index], + computed = iteratee ? iteratee(value) : value; - if (isCommon && value === value) { + if (isCommon && computed === computed) { var valuesIndex = valuesLength; while (valuesIndex--) { - if (values[valuesIndex] === value) { + if (values[valuesIndex] === computed) { continue outer; } } result.push(value); } - else if (indexOf(values, value, 0) < 0) { + else if (!includes(values, computed, comparator)) { result.push(value); } } diff --git a/internal/baseEach.js b/internal/baseEach.js index d81a68762..76cf1f2f4 100644 --- a/internal/baseEach.js +++ b/internal/baseEach.js @@ -2,13 +2,12 @@ import baseForOwn from './baseForOwn'; import createBaseEach from './createBaseEach'; /** - * The base implementation of `_.forEach` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.forEach` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. - * @returns {Array|Object|string} Returns `collection`. + * @returns {Array|Object} Returns `collection`. */ var baseEach = createBaseEach(baseForOwn); diff --git a/internal/baseEachRight.js b/internal/baseEachRight.js index f3af975ff..8b100a6d6 100644 --- a/internal/baseEachRight.js +++ b/internal/baseEachRight.js @@ -2,13 +2,12 @@ import baseForOwnRight from './baseForOwnRight'; import createBaseEach from './createBaseEach'; /** - * The base implementation of `_.forEachRight` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.forEachRight` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. - * @returns {Array|Object|string} Returns `collection`. + * @returns {Array|Object} Returns `collection`. */ var baseEachRight = createBaseEach(baseForOwnRight, true); diff --git a/internal/baseEvery.js b/internal/baseEvery.js index 6abb845da..e978a4bec 100644 --- a/internal/baseEvery.js +++ b/internal/baseEvery.js @@ -1,14 +1,12 @@ import baseEach from './baseEach'; /** - * The base implementation of `_.every` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.every` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if all elements pass the predicate check, - * else `false` + * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false` */ function baseEvery(collection, predicate) { var result = true; diff --git a/internal/baseExtremum.js b/internal/baseExtremum.js index e17dc3637..78cab39c7 100644 --- a/internal/baseExtremum.js +++ b/internal/baseExtremum.js @@ -1,28 +1,29 @@ -import baseEach from './baseEach'; - /** - * 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|key, collection). + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. * * @private - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {Function} comparator The function used to compare values. - * @param {*} exValue The initial extremum value. + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. * @returns {*} Returns the extremum value. */ -function baseExtremum(collection, iteratee, comparator, exValue) { - var computed = exValue, - result = computed; +function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; - baseEach(collection, function(value, index, collection) { - var current = +iteratee(value, index, collection); - if (comparator(current, computed) || (current === exValue && current === result)) { - computed = current; - result = value; + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? current === current + : comparator(current, computed) + )) { + var computed = current, + result = value; } - }); + } return result; } diff --git a/internal/baseFill.js b/internal/baseFill.js index bbb3e8506..57e524501 100644 --- a/internal/baseFill.js +++ b/internal/baseFill.js @@ -1,3 +1,6 @@ +import toInteger from '../toInteger'; +import toLength from '../toLength'; + /** * The base implementation of `_.fill` without an iteratee call guard. * @@ -11,18 +14,16 @@ function baseFill(array, value, start, end) { var length = array.length; - start = start == null ? 0 : (+start || 0); + start = toInteger(start); if (start < 0) { start = -start > length ? 0 : (length + start); } - end = (end === undefined || end > length) ? length : (+end || 0); + end = (end === undefined || end > length) ? length : toInteger(end); if (end < 0) { end += length; } - length = start > end ? 0 : (end >>> 0); - start >>>= 0; - - while (start < length) { + end = start > end ? 0 : toLength(end); + while (start < end) { array[start++] = value; } return array; diff --git a/internal/baseFilter.js b/internal/baseFilter.js index 278293591..5855cb5d3 100644 --- a/internal/baseFilter.js +++ b/internal/baseFilter.js @@ -1,11 +1,10 @@ import baseEach from './baseEach'; /** - * The base implementation of `_.filter` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.filter` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ diff --git a/internal/baseFind.js b/internal/baseFind.js index dcd576a7a..d229d8161 100644 --- a/internal/baseFind.js +++ b/internal/baseFind.js @@ -1,14 +1,13 @@ /** - * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, - * without support for callback shorthands and `this` binding, which iterates - * over `collection` using the provided `eachFunc`. + * The base implementation of methods like `_.find` and `_.findKey`, without + * support for iteratee shorthands, which iterates over `collection` using + * the provided `eachFunc`. * * @private - * @param {Array|Object|string} collection The collection to search. + * @param {Array|Object} collection The collection to search. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. - * @param {boolean} [retKey] Specify returning the key of the found element - * instead of the element itself. + * @param {boolean} [retKey] Specify returning the key of the found element instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ function baseFind(collection, predicate, eachFunc, retKey) { diff --git a/internal/baseFindIndex.js b/internal/baseFindIndex.js index 7beb32bc6..b40ce3a4d 100644 --- a/internal/baseFindIndex.js +++ b/internal/baseFindIndex.js @@ -1,6 +1,6 @@ /** * The base implementation of `_.findIndex` and `_.findLastIndex` without - * support for callback shorthands and `this` binding. + * support for iteratee shorthands. * * @private * @param {Array} array The array to search. diff --git a/internal/baseFlatten.js b/internal/baseFlatten.js index 35025edde..4327be6e3 100644 --- a/internal/baseFlatten.js +++ b/internal/baseFlatten.js @@ -1,12 +1,10 @@ import arrayPush from './arrayPush'; -import isArguments from '../lang/isArguments'; -import isArray from '../lang/isArray'; -import isArrayLike from './isArrayLike'; -import isObjectLike from './isObjectLike'; +import isArguments from '../isArguments'; +import isArray from '../isArray'; +import isArrayLikeObject from '../isArrayLikeObject'; /** - * The base implementation of `_.flatten` with added support for restricting - * flattening and specifying the start index. + * The base implementation of `_.flatten` with support for restricting flattening. * * @private * @param {Array} array The array to flatten. @@ -23,7 +21,7 @@ function baseFlatten(array, isDeep, isStrict, result) { while (++index < length) { var value = array[index]; - if (isObjectLike(value) && isArrayLike(value) && + if (isArrayLikeObject(value) && (isStrict || isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). diff --git a/internal/baseForIn.js b/internal/baseForIn.js index b9b56f82d..f152367fe 100644 --- a/internal/baseForIn.js +++ b/internal/baseForIn.js @@ -1,9 +1,8 @@ import baseFor from './baseFor'; -import keysIn from '../object/keysIn'; +import keysIn from '../keysIn'; /** - * The base implementation of `_.forIn` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.forIn` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. @@ -11,7 +10,7 @@ import keysIn from '../object/keysIn'; * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { - return baseFor(object, iteratee, keysIn); + return object == null ? object : baseFor(object, iteratee, keysIn); } export default baseForIn; diff --git a/internal/baseForOwn.js b/internal/baseForOwn.js index 2b60b8bb4..4ec8880ea 100644 --- a/internal/baseForOwn.js +++ b/internal/baseForOwn.js @@ -1,9 +1,8 @@ import baseFor from './baseFor'; -import keys from '../object/keys'; +import keys from '../keys'; /** - * The base implementation of `_.forOwn` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.forOwn` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. @@ -11,7 +10,7 @@ import keys from '../object/keys'; * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { - return baseFor(object, iteratee, keys); + return object && baseFor(object, iteratee, keys); } export default baseForOwn; diff --git a/internal/baseForOwnRight.js b/internal/baseForOwnRight.js index 00dcc3734..ad5fd8f04 100644 --- a/internal/baseForOwnRight.js +++ b/internal/baseForOwnRight.js @@ -1,9 +1,8 @@ import baseForRight from './baseForRight'; -import keys from '../object/keys'; +import keys from '../keys'; /** - * The base implementation of `_.forOwnRight` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. @@ -11,7 +10,7 @@ import keys from '../object/keys'; * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { - return baseForRight(object, iteratee, keys); + return object && baseForRight(object, iteratee, keys); } export default baseForOwnRight; diff --git a/internal/baseFunctions.js b/internal/baseFunctions.js index 924748204..ef2d79140 100644 --- a/internal/baseFunctions.js +++ b/internal/baseFunctions.js @@ -1,4 +1,5 @@ -import isFunction from '../lang/isFunction'; +import arrayFilter from './arrayFilter'; +import isFunction from '../isFunction'; /** * The base implementation of `_.functions` which creates an array of @@ -10,18 +11,9 @@ import isFunction from '../lang/isFunction'; * @returns {Array} Returns the new array of filtered property names. */ function baseFunctions(object, props) { - var index = -1, - length = props.length, - resIndex = -1, - result = []; - - while (++index < length) { - var key = props[index]; - if (isFunction(object[key])) { - result[++resIndex] = key; - } - } - return result; + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); } export default baseFunctions; diff --git a/internal/baseGet.js b/internal/baseGet.js index 8034d6db1..4292ed916 100644 --- a/internal/baseGet.js +++ b/internal/baseGet.js @@ -1,22 +1,17 @@ -import toObject from './toObject'; +import baseToPath from './baseToPath'; +import isKey from './isKey'; /** - * The base implementation of `get` without support for string paths - * and default values. + * The base implementation of `_.get` without support for default values. * * @private * @param {Object} object The object to query. - * @param {Array} path The path of the property to get. - * @param {string} [pathKey] The key representation of path. + * @param {Array|string} path The path of the property to get. * @returns {*} Returns the resolved value. */ -function baseGet(object, path, pathKey) { - if (object == null) { - return; - } - if (pathKey !== undefined && pathKey in toObject(object)) { - path = [pathKey]; - } +function baseGet(object, path) { + path = isKey(path, object) ? [path + ''] : baseToPath(path); + var index = 0, length = path.length; diff --git a/internal/baseHas.js b/internal/baseHas.js new file mode 100644 index 000000000..a2e44f345 --- /dev/null +++ b/internal/baseHas.js @@ -0,0 +1,26 @@ +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var getPrototypeOf = Object.getPrototypeOf; + +/** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ +function baseHas(object, key) { + // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`, + // that are composed entirely of index properties, return `false` for + // `hasOwnProperty` checks of them. + return hasOwnProperty.call(object, key) || + (typeof object == 'object' && key in object && getPrototypeOf(object) === null); +} + +export default baseHas; diff --git a/internal/baseHasIn.js b/internal/baseHasIn.js new file mode 100644 index 000000000..62ab0391c --- /dev/null +++ b/internal/baseHasIn.js @@ -0,0 +1,13 @@ +/** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ +function baseHasIn(object, key) { + return key in Object(object); +} + +export default baseHasIn; diff --git a/internal/baseInRange.js b/internal/baseInRange.js new file mode 100644 index 000000000..82636b272 --- /dev/null +++ b/internal/baseInRange.js @@ -0,0 +1,18 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * The base implementation of `_.inRange` which doesn't coerce arguments to numbers. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ +function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); +} + +export default baseInRange; diff --git a/internal/baseIndexOf.js b/internal/baseIndexOf.js index 3e14bfefb..f23611cbf 100644 --- a/internal/baseIndexOf.js +++ b/internal/baseIndexOf.js @@ -1,7 +1,7 @@ import indexOfNaN from './indexOfNaN'; /** - * The base implementation of `_.indexOf` without support for binary searches. + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. * * @private * @param {Array} array The array to search. diff --git a/internal/baseIntersection.js b/internal/baseIntersection.js new file mode 100644 index 000000000..980087c60 --- /dev/null +++ b/internal/baseIntersection.js @@ -0,0 +1,62 @@ +import SetCache from './SetCache'; +import arrayIncludes from './arrayIncludes'; +import arrayIncludesWith from './arrayIncludesWith'; +import arrayMap from './arrayMap'; +import baseUnary from './baseUnary'; +import cacheHas from './cacheHas'; + +/** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ +function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + caches[othIndex] = !comparator && (iteratee || array.length >= 120) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + length = array.length, + seen = caches[0]; + + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator))) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator))) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; +} + +export default baseIntersection; diff --git a/internal/baseInvoke.js b/internal/baseInvoke.js new file mode 100644 index 000000000..ce6fc1665 --- /dev/null +++ b/internal/baseInvoke.js @@ -0,0 +1,28 @@ +import apply from './apply'; +import baseToPath from './baseToPath'; +import isKey from './isKey'; +import last from '../last'; +import parent from './parent'; + +/** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ +function baseInvoke(object, path, args) { + if (!isKey(path, object)) { + path = baseToPath(path); + object = parent(object, path); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : apply(func, object, args); +} + +export default baseInvoke; diff --git a/internal/baseIsEqual.js b/internal/baseIsEqual.js index b594fc13f..7f06bb1e8 100644 --- a/internal/baseIsEqual.js +++ b/internal/baseIsEqual.js @@ -1,28 +1,30 @@ import baseIsEqualDeep from './baseIsEqualDeep'; -import isObject from '../lang/isObject'; -import isObjectLike from './isObjectLike'; +import isObject from '../isObject'; +import isObjectLike from '../isObjectLike'; /** - * The base implementation of `_.isEqual` without support for `this` binding - * `customizer` functions. + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @param {Function} [customizer] The function to customize comparing values. - * @param {boolean} [isLoose] Specify performing partial comparisons. - * @param {Array} [stackA] Tracks traversed `value` objects. - * @param {Array} [stackB] Tracks traversed `other` objects. + * @param {Function} [customizer] The function to customize comparisons. + * @param {boolean} [bitmask] The bitmask of comparison flags. + * The bitmask may be composed of the following flags: + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Object} [stack] Tracks traversed `value` and `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ -function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { +function baseIsEqual(value, other, customizer, bitmask, stack) { if (value === other) { return true; } if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { return value !== value && other !== other; } - return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack); } export default baseIsEqual; diff --git a/internal/baseIsEqualDeep.js b/internal/baseIsEqualDeep.js index 639f2a731..b6054bf83 100644 --- a/internal/baseIsEqualDeep.js +++ b/internal/baseIsEqualDeep.js @@ -1,26 +1,26 @@ +import Stack from './Stack'; import equalArrays from './equalArrays'; import equalByTag from './equalByTag'; import equalObjects from './equalObjects'; -import isArray from '../lang/isArray'; -import isTypedArray from '../lang/isTypedArray'; +import getTag from './getTag'; +import isArray from '../isArray'; +import isHostObject from './isHostObject'; +import isTypedArray from '../isTypedArray'; + +/** Used to compose bitmasks for comparison styles. */ +var PARTIAL_COMPARE_FLAG = 2; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', objectTag = '[object Object]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; -/** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ -var objToString = objectProto.toString; - /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular @@ -30,20 +30,19 @@ var objToString = objectProto.toString; * @param {Object} object The object to compare. * @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} [isLoose] Specify performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `value` objects. - * @param {Array} [stackB=[]] Tracks traversed `other` objects. + * @param {Function} [customizer] The function to customize comparisons. + * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { +function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; if (!objIsArr) { - objTag = objToString.call(object); + objTag = getTag(object); if (objTag == argsTag) { objTag = objectTag; } else if (objTag != objectTag) { @@ -51,52 +50,34 @@ function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, } } if (!othIsArr) { - othTag = objToString.call(other); + othTag = getTag(other); if (othTag == argsTag) { othTag = objectTag; } else if (othTag != objectTag) { othIsArr = isTypedArray(other); } } - var objIsObj = objTag == objectTag, - othIsObj = othTag == objectTag, + var objIsObj = objTag == objectTag && !isHostObject(object), + othIsObj = othTag == objectTag && !isHostObject(other), isSameTag = objTag == othTag; if (isSameTag && !(objIsArr || objIsObj)) { - return equalByTag(object, other, objTag); + return equalByTag(object, other, objTag, equalFunc, customizer, bitmask); } - if (!isLoose) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG; + if (!isPartial) { var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (objIsWrapped || othIsWrapped) { - return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, bitmask, stack); } } if (!isSameTag) { return false; } - // Assume cyclic values are equal. - // For more information on detecting circular references see https://es5.github.io/#JO. - stackA || (stackA = []); - stackB || (stackB = []); - - var length = stackA.length; - while (length--) { - if (stackA[length] == object) { - return stackB[length] == other; - } - } - // Add `object` and `other` to the stack of traversed objects. - stackA.push(object); - stackB.push(other); - - var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); - - stackA.pop(); - stackB.pop(); - - return result; + stack || (stack = new Stack); + return (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack); } export default baseIsEqualDeep; diff --git a/internal/baseIsFunction.js b/internal/baseIsFunction.js deleted file mode 100644 index d0facc551..000000000 --- a/internal/baseIsFunction.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * The base implementation of `_.isFunction` without support for environments - * with incorrect `typeof` results. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. - */ -function baseIsFunction(value) { - // Avoid a Chakra JIT bug in compatibility modes of IE 11. - // See https://github.com/jashkenas/underscore/issues/1621 for more details. - return typeof value == 'function' || false; -} - -export default baseIsFunction; diff --git a/internal/baseIsMatch.js b/internal/baseIsMatch.js index a47a8d29d..8b68cdcd2 100644 --- a/internal/baseIsMatch.js +++ b/internal/baseIsMatch.js @@ -1,17 +1,21 @@ +import Stack from './Stack'; import baseIsEqual from './baseIsEqual'; -import toObject from './toObject'; + +/** Used to compose bitmasks for comparison styles. */ +var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; /** - * The base implementation of `_.isMatch` without support for callback - * shorthands and `this` binding. + * The base implementation of `_.isMatch` without support for iteratee shorthands. * * @private * @param {Object} object The object to inspect. - * @param {Array} matchData The propery names, values, and compare flags to match. - * @param {Function} [customizer] The function to customize comparing objects. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ -function baseIsMatch(object, matchData, customizer) { +function baseIsMatch(object, source, matchData, customizer) { var index = matchData.length, length = index, noCustomizer = !customizer; @@ -19,7 +23,7 @@ function baseIsMatch(object, matchData, customizer) { if (object == null) { return !length; } - object = toObject(object); + object = Object(object); while (index--) { var data = matchData[index]; if ((noCustomizer && data[2]) @@ -40,8 +44,10 @@ function baseIsMatch(object, matchData, customizer) { return false; } } else { - var result = customizer ? customizer(objValue, srcValue, key) : undefined; - if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + var stack = new Stack, + result = customizer ? customizer(objValue, srcValue, key, object, source, stack) : undefined; + + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) : result)) { return false; } } diff --git a/internal/baseIteratee.js b/internal/baseIteratee.js new file mode 100644 index 000000000..324184ba9 --- /dev/null +++ b/internal/baseIteratee.js @@ -0,0 +1,30 @@ +import baseMatches from './baseMatches'; +import baseMatchesProperty from './baseMatchesProperty'; +import identity from '../identity'; +import isArray from '../isArray'; +import property from '../property'; + +/** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ +function baseIteratee(value) { + var type = typeof value; + if (type == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (type == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); +} + +export default baseIteratee; diff --git a/internal/baseKeys.js b/internal/baseKeys.js new file mode 100644 index 000000000..a683bc126 --- /dev/null +++ b/internal/baseKeys.js @@ -0,0 +1,17 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = Object.keys; + +/** + * The base implementation of `_.keys` which doesn't skip the constructor + * property of prototypes or treat sparse arrays as dense. + * + * @private + * @type Function + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeys(object) { + return nativeKeys(Object(object)); +} + +export default baseKeys; diff --git a/internal/baseKeysIn.js b/internal/baseKeysIn.js new file mode 100644 index 000000000..0b0979794 --- /dev/null +++ b/internal/baseKeysIn.js @@ -0,0 +1,36 @@ +import Reflect from './Reflect'; +import iteratorToArray from './iteratorToArray'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Built-in value references. */ +var enumerate = Reflect ? Reflect.enumerate : undefined, + propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * The base implementation of `_.keysIn` which doesn't skip the constructor + * property of prototypes or treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn(object) { + object = object == null ? object : Object(object); + + var result = []; + for (var key in object) { + result.push(key); + } + return result; +} + +// Fallback for IE < 9 with es6-shim. +if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) { + baseKeysIn = function(object) { + return iteratorToArray(enumerate(object)); + }; +} + +export default baseKeysIn; diff --git a/internal/baseMap.js b/internal/baseMap.js index 6f6cd346f..3b7d357ee 100644 --- a/internal/baseMap.js +++ b/internal/baseMap.js @@ -1,12 +1,11 @@ import baseEach from './baseEach'; -import isArrayLike from './isArrayLike'; +import isArrayLike from '../isArrayLike'; /** - * The base implementation of `_.map` without support for callback shorthands - * and `this` binding. + * The base implementation of `_.map` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ diff --git a/internal/baseMatches.js b/internal/baseMatches.js index d7b108455..93df4341d 100644 --- a/internal/baseMatches.js +++ b/internal/baseMatches.js @@ -1,9 +1,8 @@ import baseIsMatch from './baseIsMatch'; import getMatchData from './getMatchData'; -import toObject from './toObject'; /** - * The base implementation of `_.matches` which does not clone `source`. + * The base implementation of `_.matches` which doesn't clone `source`. * * @private * @param {Object} source The object of property values to match. @@ -19,11 +18,12 @@ function baseMatches(source) { if (object == null) { return false; } - return object[key] === value && (value !== undefined || (key in toObject(object))); + return object[key] === value && + (value !== undefined || (key in Object(object))); }; } return function(object) { - return baseIsMatch(object, matchData); + return object === source || baseIsMatch(object, source, matchData); }; } diff --git a/internal/baseMatchesProperty.js b/internal/baseMatchesProperty.js index 7f423546b..0bec4280f 100644 --- a/internal/baseMatchesProperty.js +++ b/internal/baseMatchesProperty.js @@ -1,44 +1,25 @@ -import baseGet from './baseGet'; import baseIsEqual from './baseIsEqual'; -import baseSlice from './baseSlice'; -import isArray from '../lang/isArray'; -import isKey from './isKey'; -import isStrictComparable from './isStrictComparable'; -import last from '../array/last'; -import toObject from './toObject'; -import toPath from './toPath'; +import get from '../get'; +import hasIn from '../hasIn'; + +/** Used to compose bitmasks for comparison styles. */ +var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; /** - * The base implementation of `_.matchesProperty` which does not clone `srcValue`. + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. * * @private * @param {string} path The path of the property to get. - * @param {*} srcValue The value to compare. + * @param {*} srcValue The value to match. * @returns {Function} Returns the new function. */ function baseMatchesProperty(path, srcValue) { - var isArr = isArray(path), - isCommon = isKey(path) && isStrictComparable(srcValue), - pathKey = (path + ''); - - path = toPath(path); return function(object) { - if (object == null) { - return false; - } - var key = pathKey; - object = toObject(object); - if ((isArr || !isCommon) && !(key in object)) { - object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); - if (object == null) { - return false; - } - key = last(path); - object = toObject(object); - } - return object[key] === srcValue - ? (srcValue !== undefined || (key in object)) - : baseIsEqual(srcValue, object[key], undefined, true); + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG); }; } diff --git a/internal/baseMerge.js b/internal/baseMerge.js index 703002da4..93202a71d 100644 --- a/internal/baseMerge.js +++ b/internal/baseMerge.js @@ -1,56 +1,43 @@ +import Stack from './Stack'; import arrayEach from './arrayEach'; +import assignMergeValue from './assignMergeValue'; import baseMergeDeep from './baseMergeDeep'; -import isArray from '../lang/isArray'; -import isArrayLike from './isArrayLike'; -import isObject from '../lang/isObject'; -import isObjectLike from './isObjectLike'; -import isTypedArray from '../lang/isTypedArray'; -import keys from '../object/keys'; +import isArray from '../isArray'; +import isObject from '../isObject'; +import isTypedArray from '../isTypedArray'; +import keysIn from '../keysIn'; /** - * The base implementation of `_.merge` without support for argument juggling, - * multiple sources, and `this` binding `customizer` functions. + * The base implementation of `_.merge` without support for multiple sources. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [customizer] The function to customize merged values. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates values with source counterparts. - * @returns {Object} Returns `object`. + * @param {Object} [stack] Tracks traversed source values and their merged counterparts. */ -function baseMerge(object, source, customizer, stackA, stackB) { - if (!isObject(object)) { - return object; +function baseMerge(object, source, customizer, stack) { + if (object === source) { + return; } - var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), - props = isSrcArr ? undefined : keys(source); - + var props = (isArray(source) || isTypedArray(source)) ? undefined : keysIn(source); arrayEach(props || source, function(srcValue, key) { if (props) { key = srcValue; srcValue = source[key]; } - if (isObjectLike(srcValue)) { - stackA || (stackA = []); - stackB || (stackB = []); - baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, baseMerge, customizer, stack); } else { - var value = object[key], - result = customizer ? customizer(value, srcValue, key, object, source) : undefined, - isCommon = result === undefined; - - if (isCommon) { - result = srcValue; - } - if ((result !== undefined || (isSrcArr && !(key in object))) && - (isCommon || (result === result ? (result !== value) : (value === value)))) { - object[key] = result; + var newValue = customizer ? customizer(object[key], srcValue, (key + ''), object, source, stack) : undefined; + if (newValue === undefined) { + newValue = srcValue; } + assignMergeValue(object, key, newValue); } }); - return object; } export default baseMerge; diff --git a/internal/baseMergeDeep.js b/internal/baseMergeDeep.js index 3545db5cb..9da5de47a 100644 --- a/internal/baseMergeDeep.js +++ b/internal/baseMergeDeep.js @@ -1,10 +1,14 @@ -import arrayCopy from './arrayCopy'; -import isArguments from '../lang/isArguments'; -import isArray from '../lang/isArray'; -import isArrayLike from './isArrayLike'; -import isPlainObject from '../lang/isPlainObject'; -import isTypedArray from '../lang/isTypedArray'; -import toPlainObject from '../lang/toPlainObject'; +import assignMergeValue from './assignMergeValue'; +import baseClone from './baseClone'; +import copyArray from './copyArray'; +import isArguments from '../isArguments'; +import isArray from '../isArray'; +import isArrayLikeObject from '../isArrayLikeObject'; +import isFunction from '../isFunction'; +import isObject from '../isObject'; +import isPlainObject from '../isPlainObject'; +import isTypedArray from '../isTypedArray'; +import toPlainObject from '../toPlainObject'; /** * A specialized version of `baseMerge` for arrays and objects which performs @@ -16,52 +20,44 @@ import toPlainObject from '../lang/toPlainObject'; * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize merged values. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates values with source counterparts. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged counterparts. */ -function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { - var length = stackA.length, - srcValue = source[key]; +function baseMergeDeep(object, source, key, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue) || stack.get(objValue); - while (length--) { - if (stackA[length] == srcValue) { - object[key] = stackB[length]; - return; - } + if (stacked) { + assignMergeValue(object, key, stacked); + return; } - var value = object[key], - result = customizer ? customizer(value, srcValue, key, object, source) : undefined, - isCommon = result === undefined; + var newValue = customizer ? customizer(objValue, srcValue, (key + ''), object, source, stack) : undefined, + isCommon = newValue === undefined; if (isCommon) { - result = srcValue; - if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { - result = isArray(value) - ? value - : (isArrayLike(value) ? arrayCopy(value) : []); + newValue = srcValue; + if (isArray(srcValue) || isTypedArray(srcValue)) { + newValue = isArray(objValue) + ? objValue + : ((isArrayLikeObject(objValue)) ? copyArray(objValue) : baseClone(srcValue)); } else if (isPlainObject(srcValue) || isArguments(srcValue)) { - result = isArguments(value) - ? toPlainObject(value) - : (isPlainObject(value) ? value : {}); + newValue = isArguments(objValue) + ? toPlainObject(objValue) + : (isObject(objValue) ? objValue : baseClone(srcValue)); } else { - isCommon = false; + isCommon = isFunction(srcValue); } } - // Add the source value to the stack of traversed objects and associate - // it with its merged value. - stackA.push(srcValue); - stackB.push(result); + stack.set(srcValue, newValue); if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). - object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); - } else if (result === result ? (result !== value) : (value === value)) { - object[key] = result; + mergeFunc(newValue, srcValue, customizer, stack); } + assignMergeValue(object, key, newValue); } export default baseMergeDeep; diff --git a/internal/baseOrderBy.js b/internal/baseOrderBy.js new file mode 100644 index 000000000..41dc37556 --- /dev/null +++ b/internal/baseOrderBy.js @@ -0,0 +1,36 @@ +import arrayMap from './arrayMap'; +import baseIteratee from './baseIteratee'; +import baseMap from './baseMap'; +import baseSortBy from './baseSortBy'; +import compareMultiple from './compareMultiple'; + +/** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ +function baseOrderBy(collection, iteratees, orders) { + var index = -1, + toIteratee = baseIteratee; + + iteratees = arrayMap(iteratees.length ? iteratees : Array(1), function(iteratee) { + return toIteratee(iteratee); + }); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); +} + +export default baseOrderBy; diff --git a/internal/basePick.js b/internal/basePick.js new file mode 100644 index 000000000..95f1d145b --- /dev/null +++ b/internal/basePick.js @@ -0,0 +1,22 @@ +import arrayReduce from './arrayReduce'; + +/** + * The base implementation of `_.pick` without support for individual + * property names. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. + */ +function basePick(object, props) { + object = Object(object); + return arrayReduce(props, function(result, key) { + if (key in object) { + result[key] = object[key]; + } + return result; + }, {}); +} + +export default basePick; diff --git a/internal/basePickBy.js b/internal/basePickBy.js new file mode 100644 index 000000000..24be0cfe8 --- /dev/null +++ b/internal/basePickBy.js @@ -0,0 +1,21 @@ +import baseForIn from './baseForIn'; + +/** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ +function basePickBy(object, predicate) { + var result = {}; + baseForIn(object, function(value, key) { + if (predicate(value)) { + result[key] = value; + } + }); + return result; +} + +export default basePickBy; diff --git a/internal/basePropertyDeep.js b/internal/basePropertyDeep.js index 4644bd6c0..ae817578c 100644 --- a/internal/basePropertyDeep.js +++ b/internal/basePropertyDeep.js @@ -1,5 +1,4 @@ import baseGet from './baseGet'; -import toPath from './toPath'; /** * A specialized version of `baseProperty` which supports deep paths. @@ -9,10 +8,8 @@ import toPath from './toPath'; * @returns {Function} Returns the new function. */ function basePropertyDeep(path) { - var pathKey = (path + ''); - path = toPath(path); return function(object) { - return baseGet(object, path, pathKey); + return baseGet(object, path); }; } diff --git a/internal/basePullAll.js b/internal/basePullAll.js new file mode 100644 index 000000000..68c8e5a12 --- /dev/null +++ b/internal/basePullAll.js @@ -0,0 +1,15 @@ +import basePullAllBy from './basePullAllBy'; + +/** + * The base implementation of `_.pullAll`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + */ +function basePullAll(array, values) { + return basePullAllBy(array, values); +} + +export default basePullAll; diff --git a/internal/basePullAllBy.js b/internal/basePullAllBy.js new file mode 100644 index 000000000..fd08cd9e3 --- /dev/null +++ b/internal/basePullAllBy.js @@ -0,0 +1,43 @@ +import arrayMap from './arrayMap'; +import baseIndexOf from './baseIndexOf'; + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns `array`. + */ +function basePullAllBy(array, values, iteratee) { + var index = -1, + length = values.length, + seen = array; + + if (iteratee) { + seen = arrayMap(array, function(value) { return iteratee(value); }); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = baseIndexOf(seen, computed, fromIndex)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; +} + +export default basePullAllBy; diff --git a/internal/basePullAt.js b/internal/basePullAt.js index 4cb090d57..93dcacb46 100644 --- a/internal/basePullAt.js +++ b/internal/basePullAt.js @@ -1,14 +1,18 @@ +import baseToPath from './baseToPath'; import isIndex from './isIndex'; +import isKey from './isKey'; +import last from '../last'; +import parent from './parent'; -/** Used for native method references. */ +/** Used for built-in method references. */ var arrayProto = Array.prototype; -/** Native method references. */ +/** Built-in value references. */ var splice = arrayProto.splice; /** * The base implementation of `_.pullAt` without support for individual - * index arguments and capturing the removed elements. + * indexes or capturing the removed elements. * * @private * @param {Array} array The array to modify. @@ -16,12 +20,27 @@ var splice = arrayProto.splice; * @returns {Array} Returns `array`. */ function basePullAt(array, indexes) { - var length = array ? indexes.length : 0; + var length = array ? indexes.length : 0, + lastIndex = length - 1; + while (length--) { var index = indexes[length]; - if (index != previous && isIndex(index)) { + if (lastIndex == length || index != previous) { var previous = index; - splice.call(array, index, 1); + if (isIndex(index)) { + splice.call(array, index, 1); + } + else if (!isKey(index, array)) { + var path = baseToPath(index), + object = parent(array, path); + + if (object != null) { + delete object[last(path)]; + } + } + else { + delete array[index]; + } } } return array; diff --git a/internal/baseRandom.js b/internal/baseRandom.js index f4aa8b0a8..0e6cf0302 100644 --- a/internal/baseRandom.js +++ b/internal/baseRandom.js @@ -1,18 +1,18 @@ -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeFloor = Math.floor, nativeRandom = Math.random; /** - * The base implementation of `_.random` without support for argument juggling - * and returning floating-point numbers. + * The base implementation of `_.random` without support for returning + * floating-point numbers. * * @private - * @param {number} min The minimum possible value. - * @param {number} max The maximum possible value. + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. * @returns {number} Returns the random number. */ -function baseRandom(min, max) { - return min + nativeFloor(nativeRandom() * (max - min + 1)); +function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); } export default baseRandom; diff --git a/internal/baseRange.js b/internal/baseRange.js new file mode 100644 index 000000000..0f08adf71 --- /dev/null +++ b/internal/baseRange.js @@ -0,0 +1,28 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeCeil = Math.ceil, + nativeMax = Math.max; + +/** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments to numbers. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the new array of numbers. + */ +function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; +} + +export default baseRange; diff --git a/internal/baseReduce.js b/internal/baseReduce.js index 2a7e51afb..d81fc728a 100644 --- a/internal/baseReduce.js +++ b/internal/baseReduce.js @@ -1,14 +1,13 @@ /** - * The base implementation of `_.reduce` and `_.reduceRight` without support - * for callback shorthands and `this` binding, which iterates over `collection` - * using the provided `eachFunc`. + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using the provided + * `eachFunc`. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. - * @param {boolean} initFromCollection Specify using the first or last element - * of `collection` as the initial value. + * @param {boolean} initFromCollection Specify using the first or last element of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ diff --git a/internal/baseSet.js b/internal/baseSet.js new file mode 100644 index 000000000..e73dd5847 --- /dev/null +++ b/internal/baseSet.js @@ -0,0 +1,43 @@ +import assignValue from './assignValue'; +import baseToPath from './baseToPath'; +import isIndex from './isIndex'; +import isKey from './isKey'; +import isObject from '../isObject'; + +/** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ +function baseSet(object, path, value, customizer) { + path = isKey(path, object) ? [path + ''] : baseToPath(path); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + var newValue = value; + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = objValue == null ? (isIndex(path[index + 1]) ? [] : {}) : objValue; + } + } + assignValue(nested, key, newValue); + } + nested = nested[key]; + } + return object; +} + +export default baseSet; diff --git a/internal/baseSetData.js b/internal/baseSetData.js index c2364b97a..1fd920eef 100644 --- a/internal/baseSetData.js +++ b/internal/baseSetData.js @@ -1,4 +1,4 @@ -import identity from '../utility/identity'; +import identity from '../identity'; import metaMap from './metaMap'; /** diff --git a/internal/baseSlice.js b/internal/baseSlice.js index d26a4d439..bd9c69b71 100644 --- a/internal/baseSlice.js +++ b/internal/baseSlice.js @@ -11,11 +11,10 @@ function baseSlice(array, start, end) { var index = -1, length = array.length; - start = start == null ? 0 : (+start || 0); if (start < 0) { start = -start > length ? 0 : (length + start); } - end = (end === undefined || end > length) ? length : (+end || 0); + end = end > length ? length : end; if (end < 0) { end += length; } diff --git a/internal/baseSome.js b/internal/baseSome.js index 014bff510..f33f6ea2c 100644 --- a/internal/baseSome.js +++ b/internal/baseSome.js @@ -1,14 +1,12 @@ import baseEach from './baseEach'; /** - * The base implementation of `_.some` without support for callback shorthands - * and `this` binding. + * The base implementation of `_.some` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. + * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`. */ function baseSome(collection, predicate) { var result; diff --git a/internal/baseSortByOrder.js b/internal/baseSortByOrder.js deleted file mode 100644 index 192a459d7..000000000 --- a/internal/baseSortByOrder.js +++ /dev/null @@ -1,31 +0,0 @@ -import arrayMap from './arrayMap'; -import baseCallback from './baseCallback'; -import baseMap from './baseMap'; -import baseSortBy from './baseSortBy'; -import compareMultiple from './compareMultiple'; - -/** - * The base implementation of `_.sortByOrder` without param guards. - * - * @private - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {boolean[]} orders The sort orders of `iteratees`. - * @returns {Array} Returns the new sorted array. - */ -function baseSortByOrder(collection, iteratees, orders) { - var index = -1; - - iteratees = arrayMap(iteratees, function(iteratee) { return baseCallback(iteratee); }); - - var result = baseMap(collection, function(value) { - var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); }); - return { 'criteria': criteria, 'index': ++index, 'value': value }; - }); - - return baseSortBy(result, function(object, other) { - return compareMultiple(object, other, orders); - }); -} - -export default baseSortByOrder; diff --git a/internal/binaryIndex.js b/internal/baseSortedIndex.js similarity index 71% rename from internal/binaryIndex.js rename to internal/baseSortedIndex.js index 37024e29d..4e19323ff 100644 --- a/internal/binaryIndex.js +++ b/internal/baseSortedIndex.js @@ -1,12 +1,13 @@ -import binaryIndexBy from './binaryIndexBy'; -import identity from '../utility/identity'; +import baseSortedIndexBy from './baseSortedIndexBy'; +import identity from '../identity'; /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = 4294967295, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; /** - * Performs a binary search of `array` to determine the index at which `value` + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` * should be inserted into `array` in order to maintain its sort order. * * @private @@ -16,7 +17,7 @@ var MAX_ARRAY_LENGTH = 4294967295, * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ -function binaryIndex(array, value, retHighest) { +function baseSortedIndex(array, value, retHighest) { var low = 0, high = array ? array.length : low; @@ -33,7 +34,7 @@ function binaryIndex(array, value, retHighest) { } return high; } - return binaryIndexBy(array, value, identity, retHighest); + return baseSortedIndexBy(array, value, identity, retHighest); } -export default binaryIndex; +export default baseSortedIndex; diff --git a/internal/binaryIndexBy.js b/internal/baseSortedIndexBy.js similarity index 73% rename from internal/binaryIndexBy.js rename to internal/baseSortedIndexBy.js index 1541a625f..8c035ec3b 100644 --- a/internal/binaryIndexBy.js +++ b/internal/baseSortedIndexBy.js @@ -1,25 +1,24 @@ -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeFloor = Math.floor, - nativeMin = Math.min; - /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeFloor = Math.floor, + nativeMin = Math.min; + /** - * This function is like `binaryIndex` except that it invokes `iteratee` for - * `value` and each element of `array` to compute their sort ranking. The - * iteratee is invoked with one argument; (value). + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @param {Function} iteratee The function invoked per iteration. + * @param {Function} iteratee The iteratee invoked per element. * @param {boolean} [retHighest] Specify returning the highest qualified index. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. + * @returns {number} Returns the index at which `value` should be inserted into `array`. */ -function binaryIndexBy(array, value, iteratee, retHighest) { +function baseSortedIndexBy(array, value, iteratee, retHighest) { value = iteratee(value); var low = 0, @@ -54,4 +53,4 @@ function binaryIndexBy(array, value, iteratee, retHighest) { return nativeMin(high, MAX_ARRAY_INDEX); } -export default binaryIndexBy; +export default baseSortedIndexBy; diff --git a/internal/baseSortedUniq.js b/internal/baseSortedUniq.js new file mode 100644 index 000000000..086c6b8a9 --- /dev/null +++ b/internal/baseSortedUniq.js @@ -0,0 +1,14 @@ +import baseSortedUniqBy from './baseSortedUniqBy'; + +/** + * The base implementation of `_.sortedUniq`. + * + * @private + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + */ +function baseSortedUniq(array) { + return baseSortedUniqBy(array); +} + +export default baseSortedUniq; diff --git a/internal/baseSortedUniqBy.js b/internal/baseSortedUniqBy.js new file mode 100644 index 000000000..71e552e51 --- /dev/null +++ b/internal/baseSortedUniqBy.js @@ -0,0 +1,33 @@ +import eq from '../eq'; + +/** + * The base implementation of `_.sortedUniqBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ +function baseSortedUniqBy(array, iteratee) { + var index = 0, + length = array.length, + value = array[0], + computed = iteratee ? iteratee(value) : value, + seen = computed, + resIndex = 0, + result = [value]; + + while (++index < length) { + value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!eq(computed, seen)) { + seen = computed; + result[++resIndex] = value; + } + } + return result; +} + +export default baseSortedUniqBy; diff --git a/internal/baseSum.js b/internal/baseSum.js index 53953c10e..c0e4ea5e3 100644 --- a/internal/baseSum.js +++ b/internal/baseSum.js @@ -1,19 +1,22 @@ -import baseEach from './baseEach'; - /** - * The base implementation of `_.sum` without support for callback shorthands - * and `this` binding. + * The base implementation of `_.sum` without support for iteratee shorthands. * * @private - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array} array The array 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; - }); +function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } return result; } diff --git a/internal/baseTimes.js b/internal/baseTimes.js new file mode 100644 index 000000000..d5d0e274f --- /dev/null +++ b/internal/baseTimes.js @@ -0,0 +1,20 @@ +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +export default baseTimes; diff --git a/internal/baseToPairs.js b/internal/baseToPairs.js new file mode 100644 index 000000000..ed98cf1cb --- /dev/null +++ b/internal/baseToPairs.js @@ -0,0 +1,18 @@ +import arrayMap from './arrayMap'; + +/** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the new array of key-value pairs. + */ +function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); +} + +export default baseToPairs; diff --git a/internal/baseToPath.js b/internal/baseToPath.js new file mode 100644 index 000000000..de15bc6aa --- /dev/null +++ b/internal/baseToPath.js @@ -0,0 +1,16 @@ +import isArray from '../isArray'; +import stringToPath from './stringToPath'; + +/** + * The base implementation of `_.toPath` which only converts `value` to a + * path if it's not one. + * + * @private + * @param {*} value The value to process. + * @returns {Array} Returns the property path array. + */ +function baseToPath(value) { + return isArray(value) ? value : stringToPath(value); +} + +export default baseToPath; diff --git a/internal/baseToString.js b/internal/baseToString.js deleted file mode 100644 index c9d99b53d..000000000 --- a/internal/baseToString.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Converts `value` to a string if it's not one. An empty string is returned - * for `null` or `undefined` values. - * - * @private - * @param {*} value The value to process. - * @returns {string} Returns the string. - */ -function baseToString(value) { - return value == null ? '' : (value + ''); -} - -export default baseToString; diff --git a/internal/baseUnary.js b/internal/baseUnary.js new file mode 100644 index 000000000..0419362b2 --- /dev/null +++ b/internal/baseUnary.js @@ -0,0 +1,14 @@ +/** + * The base implementation of `_.unary` without support for storing wrapper metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new function. + */ +function baseUnary(func) { + return function(value) { + return func(value); + }; +} + +export default baseUnary; diff --git a/internal/baseUniq.js b/internal/baseUniq.js index bc22b48ff..17de7c2b0 100644 --- a/internal/baseUniq.js +++ b/internal/baseUniq.js @@ -1,41 +1,52 @@ -import baseIndexOf from './baseIndexOf'; -import cacheIndexOf from './cacheIndexOf'; -import createCache from './createCache'; +import SetCache from './SetCache'; +import arrayIncludes from './arrayIncludes'; +import arrayIncludesWith from './arrayIncludesWith'; +import cacheHas from './cacheHas'; +import createSet from './createSet'; +import setToArray from './setToArray'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** - * The base implementation of `_.uniq` without support for callback shorthands - * and `this` binding. + * The base implementation of `_.uniqBy` without support for iteratee shorthands. * * @private * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function invoked per iteration. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new duplicate free array. */ -function baseUniq(array, iteratee) { +function baseUniq(array, iteratee, comparator) { var index = -1, - indexOf = baseIndexOf, + includes = arrayIncludes, length = array.length, isCommon = true, - isLarge = isCommon && length >= LARGE_ARRAY_SIZE, - seen = isLarge ? createCache() : null, - result = []; + result = [], + seen = result; - if (seen) { - indexOf = cacheIndexOf; + if (comparator) { isCommon = false; - } else { - isLarge = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], - computed = iteratee ? iteratee(value, index, array) : value; + computed = iteratee ? iteratee(value) : value; - if (isCommon && value === value) { + if (isCommon && computed === computed) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { @@ -47,8 +58,8 @@ function baseUniq(array, iteratee) { } result.push(value); } - else if (indexOf(seen, computed, 0) < 0) { - if (iteratee || isLarge) { + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { seen.push(computed); } result.push(value); diff --git a/internal/baseUnset.js b/internal/baseUnset.js new file mode 100644 index 000000000..b1c740231 --- /dev/null +++ b/internal/baseUnset.js @@ -0,0 +1,22 @@ +import baseToPath from './baseToPath'; +import has from '../has'; +import isKey from './isKey'; +import last from '../last'; +import parent from './parent'; + +/** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ +function baseUnset(object, path) { + path = isKey(path, object) ? [path + ''] : baseToPath(path); + object = parent(object, path); + var key = last(path); + return (object != null && has(object, key)) ? delete object[key] : true; +} + +export default baseUnset; diff --git a/internal/baseValues.js b/internal/baseValues.js index 935114af7..37a526e5d 100644 --- a/internal/baseValues.js +++ b/internal/baseValues.js @@ -1,3 +1,5 @@ +import arrayMap from './arrayMap'; + /** * The base implementation of `_.values` and `_.valuesIn` which creates an * array of `object` property values corresponding to the property names @@ -9,14 +11,9 @@ * @returns {Object} Returns the array of property values. */ function baseValues(object, props) { - var index = -1, - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; - } - return result; + return arrayMap(props, function(key) { + return object[key]; + }); } export default baseValues; diff --git a/internal/baseWhile.js b/internal/baseWhile.js index 997f111fa..045d539db 100644 --- a/internal/baseWhile.js +++ b/internal/baseWhile.js @@ -1,8 +1,8 @@ import baseSlice from './baseSlice'; /** - * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`, - * and `_.takeWhile` without support for callback shorthands and `this` binding. + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. * * @private * @param {Array} array The array to query. @@ -15,7 +15,9 @@ function baseWhile(array, predicate, isDrop, fromRight) { var length = array.length, index = fromRight ? length : -1; - while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + 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)); diff --git a/internal/baseWrapperValue.js b/internal/baseWrapperValue.js index 7c5c3dc83..fad9d936f 100644 --- a/internal/baseWrapperValue.js +++ b/internal/baseWrapperValue.js @@ -1,5 +1,6 @@ import LazyWrapper from './LazyWrapper'; import arrayPush from './arrayPush'; +import arrayReduce from './arrayReduce'; /** * The base implementation of `wrapperValue` which returns the result of @@ -8,7 +9,7 @@ import arrayPush from './arrayPush'; * * @private * @param {*} value The unwrapped value. - * @param {Array} actions Actions to peform to resolve the unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. * @returns {*} Returns the resolved value. */ function baseWrapperValue(value, actions) { @@ -16,14 +17,9 @@ function baseWrapperValue(value, actions) { if (result instanceof LazyWrapper) { result = result.value(); } - var index = -1, - length = actions.length; - - while (++index < length) { - var action = actions[index]; - result = action.func.apply(action.thisArg, arrayPush([result], action.args)); - } - return result; + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); } export default baseWrapperValue; diff --git a/internal/baseXor.js b/internal/baseXor.js new file mode 100644 index 000000000..96e844191 --- /dev/null +++ b/internal/baseXor.js @@ -0,0 +1,30 @@ +import arrayPush from './arrayPush'; +import baseDifference from './baseDifference'; +import baseUniq from './baseUniq'; + +/** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ +function baseXor(arrays, iteratee, comparator) { + var index = -1, + length = arrays.length; + + while (++index < length) { + var result = result + ? arrayPush( + baseDifference(result, arrays[index], iteratee, comparator), + baseDifference(arrays[index], result, iteratee, comparator) + ) + : arrays[index]; + } + return (result && result.length) ? baseUniq(result, iteratee, comparator) : []; +} + +export default baseXor; diff --git a/internal/bindCallback.js b/internal/bindCallback.js deleted file mode 100644 index ca3397e8a..000000000 --- a/internal/bindCallback.js +++ /dev/null @@ -1,39 +0,0 @@ -import identity from '../utility/identity'; - -/** - * A specialized version of `baseCallback` which only supports `this` binding - * and specifying the number of arguments to provide to `func`. - * - * @private - * @param {Function} func The function to bind. - * @param {*} thisArg The `this` binding of `func`. - * @param {number} [argCount] The number of arguments to provide to `func`. - * @returns {Function} Returns the callback. - */ -function bindCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; - } - if (thisArg === undefined) { - return func; - } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; - case 5: return function(value, other, key, object, source) { - return func.call(thisArg, value, other, key, object, source); - }; - } - return function() { - return func.apply(thisArg, arguments); - }; -} - -export default bindCallback; diff --git a/internal/bufferClone.js b/internal/bufferClone.js deleted file mode 100644 index acf2f60f1..000000000 --- a/internal/bufferClone.js +++ /dev/null @@ -1,22 +0,0 @@ -import root from './root'; - -/** Native method references. */ -var ArrayBuffer = root.ArrayBuffer, - Uint8Array = root.Uint8Array; - -/** - * Creates a clone of the given array buffer. - * - * @private - * @param {ArrayBuffer} buffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. - */ -function bufferClone(buffer) { - var result = new ArrayBuffer(buffer.byteLength), - view = new Uint8Array(result); - - view.set(new Uint8Array(buffer)); - return result; -} - -export default bufferClone; diff --git a/internal/cacheHas.js b/internal/cacheHas.js new file mode 100644 index 000000000..a3d401ff6 --- /dev/null +++ b/internal/cacheHas.js @@ -0,0 +1,25 @@ +import isKeyable from './isKeyable'; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Checks if `value` is in `cache`. + * + * @private + * @param {Object} cache The set cache to search. + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function cacheHas(cache, value) { + var map = cache.__data__; + if (isKeyable(value)) { + var data = map.__data__, + hash = typeof value == 'string' ? data.string : data.hash; + + return hash[value] === HASH_UNDEFINED; + } + return map.has(value); +} + +export default cacheHas; diff --git a/internal/cacheIndexOf.js b/internal/cacheIndexOf.js deleted file mode 100644 index 700fc3caa..000000000 --- a/internal/cacheIndexOf.js +++ /dev/null @@ -1,19 +0,0 @@ -import isObject from '../lang/isObject'; - -/** - * Checks if `value` is in `cache` mimicking the return signature of - * `_.indexOf` by returning `0` if the value is found, else `-1`. - * - * @private - * @param {Object} cache The cache to search. - * @param {*} value The value to search for. - * @returns {number} Returns `0` if `value` is found, else `-1`. - */ -function cacheIndexOf(cache, value) { - var data = cache.data, - result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value]; - - return result ? 0 : -1; -} - -export default cacheIndexOf; diff --git a/internal/cachePush.js b/internal/cachePush.js index 93a60cfe7..27b972253 100644 --- a/internal/cachePush.js +++ b/internal/cachePush.js @@ -1,7 +1,10 @@ -import isObject from '../lang/isObject'; +import isKeyable from './isKeyable'; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; /** - * Adds `value` to the cache. + * Adds `value` to the set cache. * * @private * @name push @@ -9,11 +12,15 @@ import isObject from '../lang/isObject'; * @param {*} value The value to cache. */ function cachePush(value) { - var data = this.data; - if (typeof value == 'string' || isObject(value)) { - data.set.add(value); - } else { - data.hash[value] = true; + var map = this.__data__; + if (isKeyable(value)) { + var data = map.__data__, + hash = typeof value == 'string' ? data.string : data.hash; + + hash[value] = HASH_UNDEFINED; + } + else { + map.set(value, HASH_UNDEFINED); } } diff --git a/internal/charsEndIndex.js b/internal/charsEndIndex.js new file mode 100644 index 000000000..2a8f730ad --- /dev/null +++ b/internal/charsEndIndex.js @@ -0,0 +1,19 @@ +import baseIndexOf from './baseIndexOf'; + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ +function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +export default charsEndIndex; diff --git a/internal/charsLeftIndex.js b/internal/charsLeftIndex.js deleted file mode 100644 index cfe5fc2e6..000000000 --- a/internal/charsLeftIndex.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Used by `_.trim` and `_.trimLeft` to get the index of the first character - * of `string` that is not found in `chars`. - * - * @private - * @param {string} string The string to inspect. - * @param {string} chars The characters to find. - * @returns {number} Returns the index of the first character not found in `chars`. - */ -function charsLeftIndex(string, chars) { - var index = -1, - length = string.length; - - while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} - return index; -} - -export default charsLeftIndex; diff --git a/internal/charsRightIndex.js b/internal/charsRightIndex.js deleted file mode 100644 index 2cc439637..000000000 --- a/internal/charsRightIndex.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Used by `_.trim` and `_.trimRight` to get the index of the last character - * of `string` that is not found in `chars`. - * - * @private - * @param {string} string The string to inspect. - * @param {string} chars The characters to find. - * @returns {number} Returns the index of the last character not found in `chars`. - */ -function charsRightIndex(string, chars) { - var index = string.length; - - while (index-- && chars.indexOf(string.charAt(index)) > -1) {} - return index; -} - -export default charsRightIndex; diff --git a/internal/charsStartIndex.js b/internal/charsStartIndex.js new file mode 100644 index 000000000..6ceb43491 --- /dev/null +++ b/internal/charsStartIndex.js @@ -0,0 +1,20 @@ +import baseIndexOf from './baseIndexOf'; + +/** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ +function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +export default charsStartIndex; diff --git a/internal/checkGlobal.js b/internal/checkGlobal.js new file mode 100644 index 000000000..523609a94 --- /dev/null +++ b/internal/checkGlobal.js @@ -0,0 +1,12 @@ +/** + * Checks if `value` is a global object. + * + * @private + * @param {*} value The value to check. + * @returns {null|Object} Returns `value` if it's a global object, else `null`. + */ +function checkGlobal(value) { + return (value && value.Object === Object) ? value : null; +} + +export default checkGlobal; diff --git a/internal/cloneBuffer.js b/internal/cloneBuffer.js new file mode 100644 index 000000000..5e56ba0ac --- /dev/null +++ b/internal/cloneBuffer.js @@ -0,0 +1,19 @@ +import Uint8Array from './Uint8Array'; + +/** + * Creates a clone of `buffer`. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneBuffer(buffer) { + var Ctor = buffer.constructor, + result = new Ctor(buffer.byteLength), + view = new Uint8Array(result); + + view.set(new Uint8Array(buffer)); + return result; +} + +export default cloneBuffer; diff --git a/internal/cloneMap.js b/internal/cloneMap.js new file mode 100644 index 000000000..cb54bdaa1 --- /dev/null +++ b/internal/cloneMap.js @@ -0,0 +1,17 @@ +import addMapEntry from './addMapEntry'; +import arrayReduce from './arrayReduce'; +import mapToArray from './mapToArray'; + +/** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @returns {Object} Returns the cloned map. + */ +function cloneMap(map) { + var Ctor = map.constructor; + return arrayReduce(mapToArray(map), addMapEntry, new Ctor); +} + +export default cloneMap; diff --git a/internal/cloneRegExp.js b/internal/cloneRegExp.js new file mode 100644 index 000000000..4942fa44b --- /dev/null +++ b/internal/cloneRegExp.js @@ -0,0 +1,19 @@ +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ +function cloneRegExp(regexp) { + var Ctor = regexp.constructor, + result = new Ctor(regexp.source, reFlags.exec(regexp)); + + result.lastIndex = regexp.lastIndex; + return result; +} + +export default cloneRegExp; diff --git a/internal/cloneSet.js b/internal/cloneSet.js new file mode 100644 index 000000000..44c6f7c48 --- /dev/null +++ b/internal/cloneSet.js @@ -0,0 +1,17 @@ +import addSetEntry from './addSetEntry'; +import arrayReduce from './arrayReduce'; +import setToArray from './setToArray'; + +/** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @returns {Object} Returns the cloned set. + */ +function cloneSet(set) { + var Ctor = set.constructor; + return arrayReduce(setToArray(set), addSetEntry, new Ctor); +} + +export default cloneSet; diff --git a/internal/cloneSymbol.js b/internal/cloneSymbol.js new file mode 100644 index 000000000..4bc4c587a --- /dev/null +++ b/internal/cloneSymbol.js @@ -0,0 +1,18 @@ +import _Symbol from './_Symbol'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = _Symbol ? _Symbol.prototype : undefined, + symbolValueOf = _Symbol ? symbolProto.valueOf : undefined; + +/** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ +function cloneSymbol(symbol) { + return _Symbol ? Object(symbolValueOf.call(symbol)) : {}; +} + +export default cloneSymbol; diff --git a/internal/cloneTypedArray.js b/internal/cloneTypedArray.js new file mode 100644 index 000000000..95c2c40ee --- /dev/null +++ b/internal/cloneTypedArray.js @@ -0,0 +1,18 @@ +import cloneBuffer from './cloneBuffer'; + +/** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ +function cloneTypedArray(typedArray, isDeep) { + var buffer = typedArray.buffer, + Ctor = typedArray.constructor; + + return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, typedArray.byteOffset, typedArray.length); +} + +export default cloneTypedArray; diff --git a/internal/compareAscending.js b/internal/compareAscending.js index a908e8080..8d048f9aa 100644 --- a/internal/compareAscending.js +++ b/internal/compareAscending.js @@ -1,16 +1,33 @@ -import baseCompareAscending from './baseCompareAscending'; - /** - * Used by `_.sortBy` to compare transformed elements of a collection and stable - * sort them in ascending order. + * Compares values to sort them in ascending order. * * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @returns {number} Returns the sort order indicator for `object`. + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. */ -function compareAscending(object, other) { - return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index); +function compareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, + valIsUndef = value === undefined, + valIsReflexive = value === value; + + var othIsNull = other === null, + othIsUndef = other === undefined, + othIsReflexive = other === other; + + if ((value > other && !othIsNull) || !valIsReflexive || + (valIsNull && !othIsUndef && othIsReflexive) || + (valIsUndef && othIsReflexive)) { + return 1; + } + if ((value < other && !valIsNull) || !othIsReflexive || + (othIsNull && !valIsUndef && valIsReflexive) || + (othIsUndef && valIsReflexive)) { + return -1; + } + } + return 0; } export default compareAscending; diff --git a/internal/compareMultiple.js b/internal/compareMultiple.js index ad3e1721e..323c24216 100644 --- a/internal/compareMultiple.js +++ b/internal/compareMultiple.js @@ -1,17 +1,17 @@ -import baseCompareAscending from './baseCompareAscending'; +import compareAscending from './compareAscending'; /** - * Used by `_.sortByOrder` to compare multiple properties of a value to another + * Used by `_.orderBy` to compare multiple properties of a value to another * and stable sort them. * - * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise, - * a value is sorted in ascending order if its corresponding order is "asc", and - * descending if "desc". + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. - * @param {boolean[]} orders The order to sort by for each property. + * @param {boolean[]|string[]} orders The order to sort by for each property. * @returns {number} Returns the sort order indicator for `object`. */ function compareMultiple(object, other, orders) { @@ -22,13 +22,13 @@ function compareMultiple(object, other, orders) { ordersLength = orders.length; while (++index < length) { - var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + var result = compareAscending(objCriteria[index], othCriteria[index]); if (result) { if (index >= ordersLength) { return result; } var order = orders[index]; - return result * ((order === 'asc' || order === true) ? 1 : -1); + return result * (order == 'desc' ? -1 : 1); } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications diff --git a/internal/composeArgs.js b/internal/composeArgs.js index d89463f9a..854f489aa 100644 --- a/internal/composeArgs.js +++ b/internal/composeArgs.js @@ -1,4 +1,4 @@ -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; /** diff --git a/internal/composeArgsRight.js b/internal/composeArgsRight.js index 0886f3cbb..48b059c8c 100644 --- a/internal/composeArgsRight.js +++ b/internal/composeArgsRight.js @@ -1,4 +1,4 @@ -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; /** diff --git a/internal/arrayCopy.js b/internal/copyArray.js similarity index 86% rename from internal/arrayCopy.js rename to internal/copyArray.js index 0b34ccb98..b29b71e95 100644 --- a/internal/arrayCopy.js +++ b/internal/copyArray.js @@ -6,7 +6,7 @@ * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ -function arrayCopy(source, array) { +function copyArray(source, array) { var index = -1, length = source.length; @@ -17,4 +17,4 @@ function arrayCopy(source, array) { return array; } -export default arrayCopy; +export default copyArray; diff --git a/internal/baseCopy.js b/internal/copyObject.js similarity index 53% rename from internal/baseCopy.js rename to internal/copyObject.js index be5759522..1e7050819 100644 --- a/internal/baseCopy.js +++ b/internal/copyObject.js @@ -1,3 +1,5 @@ +import copyObjectWith from './copyObjectWith'; + /** * Copies properties of `source` to `object`. * @@ -7,17 +9,8 @@ * @param {Object} [object={}] The object to copy properties to. * @returns {Object} Returns `object`. */ -function baseCopy(source, props, object) { - object || (object = {}); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; - object[key] = source[key]; - } - return object; +function copyObject(source, props, object) { + return copyObjectWith(source, props, object); } -export default baseCopy; +export default copyObject; diff --git a/internal/copyObjectWith.js b/internal/copyObjectWith.js new file mode 100644 index 000000000..46adee9b3 --- /dev/null +++ b/internal/copyObjectWith.js @@ -0,0 +1,29 @@ +import assignValue from './assignValue'; + +/** + * This function is like `copyObject` except that it accepts a function to + * customize copied values. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property names to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObjectWith(source, props, object, customizer) { + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index], + newValue = customizer ? customizer(object[key], source[key], key, object, source) : source[key]; + + assignValue(object, key, newValue); + } + return object; +} + +export default copyObjectWith; diff --git a/internal/copySymbols.js b/internal/copySymbols.js new file mode 100644 index 000000000..854798050 --- /dev/null +++ b/internal/copySymbols.js @@ -0,0 +1,16 @@ +import copyObject from './copyObject'; +import getSymbols from './getSymbols'; + +/** + * Copies own symbol properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); +} + +export default copySymbols; diff --git a/internal/createAggregator.js b/internal/createAggregator.js index 5aee6a0df..f53259456 100644 --- a/internal/createAggregator.js +++ b/internal/createAggregator.js @@ -1,9 +1,9 @@ -import baseCallback from './baseCallback'; import baseEach from './baseEach'; -import isArray from '../lang/isArray'; +import baseIteratee from './baseIteratee'; +import isArray from '../isArray'; /** - * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function. + * Creates a function like `_.groupBy`. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. @@ -11,9 +11,9 @@ import isArray from '../lang/isArray'; * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { - return function(collection, iteratee, thisArg) { + return function(collection, iteratee) { var result = initializer ? initializer() : {}; - iteratee = baseCallback(iteratee, thisArg, 3); + iteratee = baseIteratee(iteratee); if (isArray(collection)) { var index = -1, @@ -21,11 +21,11 @@ function createAggregator(setter, initializer) { while (++index < length) { var value = collection[index]; - setter(result, value, iteratee(value, index, collection), collection); + setter(result, value, iteratee(value), collection); } } else { baseEach(collection, function(value, key, collection) { - setter(result, value, iteratee(value, key, collection), collection); + setter(result, value, iteratee(value), collection); }); } return result; diff --git a/internal/createAssigner.js b/internal/createAssigner.js index 184c2a317..0dd9da9b2 100644 --- a/internal/createAssigner.js +++ b/internal/createAssigner.js @@ -1,33 +1,26 @@ -import bindCallback from './bindCallback'; import isIterateeCall from './isIterateeCall'; -import restParam from '../function/restParam'; +import rest from '../rest'; /** - * Creates a `_.assign`, `_.defaults`, or `_.merge` function. + * Creates a function like `_.assign`. * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { - return restParam(function(object, sources) { + return rest(function(object, sources) { var index = -1, - length = object == null ? 0 : sources.length, - customizer = length > 2 ? sources[length - 2] : undefined, - guard = length > 2 ? sources[2] : undefined, - thisArg = length > 1 ? sources[length - 1] : undefined; + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; - if (typeof customizer == 'function') { - customizer = bindCallback(customizer, thisArg, 5); - length -= 2; - } else { - customizer = typeof thisArg == 'function' ? thisArg : undefined; - length -= (customizer ? 1 : 0); - } + customizer = typeof customizer == 'function' ? (length--, customizer) : undefined; if (guard && isIterateeCall(sources[0], sources[1], guard)) { customizer = length < 3 ? undefined : customizer; length = 1; } + object = Object(object); while (++index < length) { var source = sources[index]; if (source) { diff --git a/internal/createBaseEach.js b/internal/createBaseEach.js index 4a28c9351..f3b527edb 100644 --- a/internal/createBaseEach.js +++ b/internal/createBaseEach.js @@ -1,6 +1,4 @@ -import getLength from './getLength'; -import isLength from './isLength'; -import toObject from './toObject'; +import isArrayLike from '../isArrayLike'; /** * Creates a `baseEach` or `baseEachRight` function. @@ -12,12 +10,15 @@ import toObject from './toObject'; */ function createBaseEach(eachFunc, fromRight) { return function(collection, iteratee) { - var length = collection ? getLength(collection) : 0; - if (!isLength(length)) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { return eachFunc(collection, iteratee); } - var index = fromRight ? length : -1, - iterable = toObject(collection); + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); while ((fromRight ? index-- : ++index < length)) { if (iteratee(iterable[index], index, iterable) === false) { diff --git a/internal/createBaseFor.js b/internal/createBaseFor.js index 0bc9540b2..97249e7de 100644 --- a/internal/createBaseFor.js +++ b/internal/createBaseFor.js @@ -1,7 +1,5 @@ -import toObject from './toObject'; - /** - * Creates a base function for `_.forIn` or `_.forInRight`. + * Creates a base function for methods like `_.forIn`. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. @@ -9,13 +7,13 @@ import toObject from './toObject'; */ function createBaseFor(fromRight) { return function(object, iteratee, keysFunc) { - var iterable = toObject(object), + var index = -1, + iterable = Object(object), props = keysFunc(object), - length = props.length, - index = fromRight ? length : -1; + length = props.length; - while ((fromRight ? index-- : ++index < length)) { - var key = props[index]; + while (length--) { + var key = props[fromRight ? length : ++index]; if (iteratee(iterable[key], key, iterable) === false) { break; } diff --git a/internal/createBaseWrapper.js b/internal/createBaseWrapper.js new file mode 100644 index 000000000..6693eaafa --- /dev/null +++ b/internal/createBaseWrapper.js @@ -0,0 +1,28 @@ +import createCtorWrapper from './createCtorWrapper'; +import root from './root'; + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1; + +/** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createBaseWrapper(func, bitmask, thisArg) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtorWrapper(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; +} + +export default createBaseWrapper; diff --git a/internal/createBindWrapper.js b/internal/createBindWrapper.js deleted file mode 100644 index 19cd166ce..000000000 --- a/internal/createBindWrapper.js +++ /dev/null @@ -1,23 +0,0 @@ -import createCtorWrapper from './createCtorWrapper'; -import root from './root'; - -/** - * Creates a function that wraps `func` and invokes it with the `this` - * binding of `thisArg`. - * - * @private - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @returns {Function} Returns the new bound function. - */ -function createBindWrapper(func, thisArg) { - var Ctor = createCtorWrapper(func); - - function wrapper() { - var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; - return fn.apply(thisArg, arguments); - } - return wrapper; -} - -export default createBindWrapper; diff --git a/internal/createCache.js b/internal/createCache.js deleted file mode 100644 index f7606a1cf..000000000 --- a/internal/createCache.js +++ /dev/null @@ -1,22 +0,0 @@ -import SetCache from './SetCache'; -import getNative from './getNative'; -import root from './root'; - -/** Native method references. */ -var Set = getNative(root, 'Set'); - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeCreate = getNative(Object, 'create'); - -/** - * Creates a `Set` cache object to optimize linear searches of large arrays. - * - * @private - * @param {Array} [values] The values to cache. - * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. - */ -function createCache(values) { - return (nativeCreate && Set) ? new SetCache(values) : null; -} - -export default createCache; diff --git a/internal/createCaseFirst.js b/internal/createCaseFirst.js new file mode 100644 index 000000000..419286fcb --- /dev/null +++ b/internal/createCaseFirst.js @@ -0,0 +1,34 @@ +import stringToArray from './stringToArray'; +import toString from '../toString'; + +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new function. + */ +function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = reHasComplexSymbol.test(string) ? stringToArray(string) : undefined, + chr = strSymbols ? strSymbols[0] : string.charAt(0), + trailing = strSymbols ? strSymbols.slice(1).join('') : string.slice(1); + + return chr[methodName]() + trailing; + }; +} + +export default createCaseFirst; diff --git a/internal/createCompounder.js b/internal/createCompounder.js index 144dd09a6..6178cdab3 100644 --- a/internal/createCompounder.js +++ b/internal/createCompounder.js @@ -1,9 +1,9 @@ -import deburr from '../string/deburr'; -import words from '../string/words'; +import arrayReduce from './arrayReduce'; +import deburr from '../deburr'; +import words from '../words'; /** - * Creates a function that produces compound words out of the words in a - * given string. + * Creates a function like `_.camelCase`. * * @private * @param {Function} callback The function to combine each word. @@ -11,15 +11,7 @@ import words from '../string/words'; */ function createCompounder(callback) { return function(string) { - var index = -1, - array = words(deburr(string)), - length = array.length, - result = ''; - - while (++index < length) { - result = callback(result, array[index], index); - } - return result; + return arrayReduce(words(deburr(string)), callback, ''); }; } diff --git a/internal/createCtorWrapper.js b/internal/createCtorWrapper.js index b05cb162a..331cd0f08 100644 --- a/internal/createCtorWrapper.js +++ b/internal/createCtorWrapper.js @@ -1,5 +1,5 @@ import baseCreate from './baseCreate'; -import isObject from '../lang/isObject'; +import isObject from '../isObject'; /** * Creates a function that produces an instance of `Ctor` regardless of diff --git a/internal/createCurry.js b/internal/createCurry.js deleted file mode 100644 index 03c8c6cce..000000000 --- a/internal/createCurry.js +++ /dev/null @@ -1,23 +0,0 @@ -import createWrapper from './createWrapper'; -import isIterateeCall from './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 = undefined; - } - var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); - result.placeholder = curryFunc.placeholder; - return result; - } - return curryFunc; -} - -export default createCurry; diff --git a/internal/createCurryWrapper.js b/internal/createCurryWrapper.js new file mode 100644 index 000000000..1fb8b1f86 --- /dev/null +++ b/internal/createCurryWrapper.js @@ -0,0 +1,42 @@ +import apply from './apply'; +import createCtorWrapper from './createCtorWrapper'; +import createHybridWrapper from './createHybridWrapper'; +import createRecurryWrapper from './createRecurryWrapper'; +import replaceHolders from './replaceHolders'; +import root from './root'; + +/** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createCurryWrapper(func, bitmask, arity) { + var Ctor = createCtorWrapper(func); + + function wrapper() { + var length = arguments.length, + index = length, + args = Array(length), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func, + placeholder = wrapper.placeholder; + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + return length < arity + ? createRecurryWrapper(func, bitmask, createHybridWrapper, placeholder, undefined, args, holders, undefined, undefined, arity - length) + : apply(fn, this, args); + } + return wrapper; +} + +export default createCurryWrapper; diff --git a/internal/createDefaults.js b/internal/createDefaults.js deleted file mode 100644 index 5fa865d63..000000000 --- a/internal/createDefaults.js +++ /dev/null @@ -1,22 +0,0 @@ -import restParam from '../function/restParam'; - -/** - * Creates a `_.defaults` or `_.defaultsDeep` function. - * - * @private - * @param {Function} assigner The function to assign values. - * @param {Function} customizer The function to customize assigned values. - * @returns {Function} Returns the new defaults function. - */ -function createDefaults(assigner, customizer) { - return restParam(function(args) { - var object = args[0]; - if (object == null) { - return object; - } - args.push(customizer); - return assigner.apply(undefined, args); - }); -} - -export default createDefaults; diff --git a/internal/createExtremum.js b/internal/createExtremum.js deleted file mode 100644 index 82ad48d0f..000000000 --- a/internal/createExtremum.js +++ /dev/null @@ -1,33 +0,0 @@ -import arrayExtremum from './arrayExtremum'; -import baseCallback from './baseCallback'; -import baseExtremum from './baseExtremum'; -import isArray from '../lang/isArray'; -import isIterateeCall from './isIterateeCall'; -import toIterable from './toIterable'; - -/** - * Creates a `_.max` or `_.min` function. - * - * @private - * @param {Function} comparator The function used to compare values. - * @param {*} exValue The initial extremum value. - * @returns {Function} Returns the new extremum function. - */ -function createExtremum(comparator, exValue) { - return function(collection, iteratee, thisArg) { - if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = undefined; - } - iteratee = baseCallback(iteratee, thisArg, 3); - if (iteratee.length == 1) { - collection = isArray(collection) ? collection : toIterable(collection); - var result = arrayExtremum(collection, iteratee, comparator, exValue); - if (!(collection.length && result === exValue)) { - return result; - } - } - return baseExtremum(collection, iteratee, comparator, exValue); - }; -} - -export default createExtremum; diff --git a/internal/createFind.js b/internal/createFind.js deleted file mode 100644 index 8445c9651..000000000 --- a/internal/createFind.js +++ /dev/null @@ -1,25 +0,0 @@ -import baseCallback from './baseCallback'; -import baseFind from './baseFind'; -import baseFindIndex from './baseFindIndex'; -import isArray from '../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); - }; -} - -export default createFind; diff --git a/internal/createFindIndex.js b/internal/createFindIndex.js deleted file mode 100644 index a9b8cf7cc..000000000 --- a/internal/createFindIndex.js +++ /dev/null @@ -1,21 +0,0 @@ -import baseCallback from './baseCallback'; -import baseFindIndex from './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); - }; -} - -export default createFindIndex; diff --git a/internal/createFindKey.js b/internal/createFindKey.js deleted file mode 100644 index f51ac2b31..000000000 --- a/internal/createFindKey.js +++ /dev/null @@ -1,18 +0,0 @@ -import baseCallback from './baseCallback'; -import baseFind from './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); - }; -} - -export default createFindKey; diff --git a/internal/createFlow.js b/internal/createFlow.js index 970415842..dd0371a58 100644 --- a/internal/createFlow.js +++ b/internal/createFlow.js @@ -1,8 +1,10 @@ import LodashWrapper from './LodashWrapper'; +import baseFlatten from './baseFlatten'; import getData from './getData'; import getFuncName from './getFuncName'; -import isArray from '../lang/isArray'; +import isArray from '../isArray'; import isLaziable from './isLaziable'; +import rest from '../rest'; /** Used to compose bitmasks for wrapper metadata. */ var CURRY_FLAG = 8, @@ -24,23 +26,26 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * @returns {Function} Returns the new flow function. */ function createFlow(fromRight) { - return function() { - var wrapper, - length = arguments.length, - index = fromRight ? length : -1, - leftIndex = 0, - funcs = Array(length); + return rest(function(funcs) { + funcs = baseFlatten(funcs); - while ((fromRight ? index-- : ++index < length)) { - var func = funcs[leftIndex++] = arguments[index]; + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') { - wrapper = new LodashWrapper([], true); + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); } } - index = wrapper ? -1 : length; + index = wrapper ? index : length; while (++index < length) { func = funcs[index]; @@ -68,7 +73,7 @@ function createFlow(fromRight) { } return result; }; - }; + }); } export default createFlow; diff --git a/internal/createForEach.js b/internal/createForEach.js deleted file mode 100644 index fd213aefe..000000000 --- a/internal/createForEach.js +++ /dev/null @@ -1,20 +0,0 @@ -import bindCallback from './bindCallback'; -import isArray from '../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' && thisArg === undefined && isArray(collection)) - ? arrayFunc(collection, iteratee) - : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); - }; -} - -export default createForEach; diff --git a/internal/createForIn.js b/internal/createForIn.js deleted file mode 100644 index 22ffa4e93..000000000 --- a/internal/createForIn.js +++ /dev/null @@ -1,20 +0,0 @@ -import bindCallback from './bindCallback'; -import keysIn from '../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' || thisArg !== undefined) { - iteratee = bindCallback(iteratee, thisArg, 3); - } - return objectFunc(object, iteratee, keysIn); - }; -} - -export default createForIn; diff --git a/internal/createForOwn.js b/internal/createForOwn.js deleted file mode 100644 index cf912cfdf..000000000 --- a/internal/createForOwn.js +++ /dev/null @@ -1,19 +0,0 @@ -import bindCallback from './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' || thisArg !== undefined) { - iteratee = bindCallback(iteratee, thisArg, 3); - } - return objectFunc(object, iteratee); - }; -} - -export default createForOwn; diff --git a/internal/createHybridWrapper.js b/internal/createHybridWrapper.js index 5ceed61aa..be81ece05 100644 --- a/internal/createHybridWrapper.js +++ b/internal/createHybridWrapper.js @@ -1,33 +1,26 @@ -import arrayCopy from './arrayCopy'; import composeArgs from './composeArgs'; import composeArgsRight from './composeArgsRight'; import createCtorWrapper from './createCtorWrapper'; -import isLaziable from './isLaziable'; +import createRecurryWrapper from './createRecurryWrapper'; import reorder from './reorder'; import replaceHolders from './replaceHolders'; import root from './root'; -import setData from './setData'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, - CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, - PARTIAL_FLAG = 32, - PARTIAL_RIGHT_FLAG = 64, - ARY_FLAG = 128; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; + ARY_FLAG = 128, + FLIP_FLAG = 512; /** - * Creates a function that wraps `func` and invokes it with optional `this` - * binding of, partial application, and currying. + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. * * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to prepend to those provided to the new function. * @param {Array} [holders] The `partials` placeholder indexes. @@ -43,13 +36,11 @@ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partials isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, + isFlip = bitmask & FLIP_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { - // Avoid `arguments` object use disqualifying optimizations by - // converting it to an array before providing it to other functions. var length = arguments.length, index = length, args = Array(length); @@ -69,27 +60,7 @@ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partials length -= argsHolders.length; if (length < arity) { - var newArgPos = argPos ? arrayCopy(argPos) : undefined, - newArity = nativeMax(arity - length, 0), - newsHolders = isCurry ? argsHolders : undefined, - newHoldersRight = isCurry ? undefined : argsHolders, - newPartials = isCurry ? args : undefined, - newPartialsRight = isCurry ? undefined : args; - - bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); - bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); - - if (!isCurryBound) { - bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); - } - 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; + return createRecurryWrapper(func, bitmask, createHybridWrapper, placeholder, thisArg, args, argsHolders, argPos, ary, arity - length); } } var thisBinding = isBind ? thisArg : this, @@ -97,12 +68,14 @@ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partials if (argPos) { args = reorder(args, argPos); + } else if (isFlip && args.length > 1) { + args.reverse(); } if (isAry && ary < args.length) { args.length = ary; } if (this && this !== root && this instanceof wrapper) { - fn = Ctor || createCtorWrapper(func); + fn = Ctor || createCtorWrapper(fn); } return fn.apply(thisBinding, args); } diff --git a/internal/createObjectMapper.js b/internal/createObjectMapper.js deleted file mode 100644 index e0d1b8e30..000000000 --- a/internal/createObjectMapper.js +++ /dev/null @@ -1,26 +0,0 @@ -import baseCallback from './baseCallback'; -import baseForOwn from './baseForOwn'; - -/** - * Creates a function for `_.mapKeys` or `_.mapValues`. - * - * @private - * @param {boolean} [isMapKeys] Specify mapping keys instead of values. - * @returns {Function} Returns the new map function. - */ -function createObjectMapper(isMapKeys) { - return function(object, iteratee, thisArg) { - var result = {}; - iteratee = baseCallback(iteratee, thisArg, 3); - - baseForOwn(object, function(value, key, object) { - var mapped = iteratee(value, key, object); - key = isMapKeys ? mapped : key; - value = isMapKeys ? value : mapped; - result[key] = value; - }); - return result; - }; -} - -export default createObjectMapper; diff --git a/internal/createOver.js b/internal/createOver.js new file mode 100644 index 000000000..0722c595e --- /dev/null +++ b/internal/createOver.js @@ -0,0 +1,26 @@ +import apply from './apply'; +import arrayMap from './arrayMap'; +import baseFlatten from './baseFlatten'; +import baseIteratee from './baseIteratee'; +import rest from '../rest'; + +/** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new invoker function. + */ +function createOver(arrayFunc) { + return rest(function(iteratees) { + iteratees = arrayMap(baseFlatten(iteratees), baseIteratee); + return rest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); +} + +export default createOver; diff --git a/internal/createPadDir.js b/internal/createPadDir.js deleted file mode 100644 index e2ee0d72b..000000000 --- a/internal/createPadDir.js +++ /dev/null @@ -1,18 +0,0 @@ -import baseToString from './baseToString'; -import createPadding from './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 (fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string); - }; -} - -export default createPadDir; diff --git a/internal/createPadding.js b/internal/createPadding.js index f7a0fbf4f..5b5e1620f 100644 --- a/internal/createPadding.js +++ b/internal/createPadding.js @@ -1,30 +1,46 @@ -import repeat from '../string/repeat'; -import root from './root'; +import repeat from '../repeat'; +import stringSize from './stringSize'; +import stringToArray from './stringToArray'; +import toInteger from '../toInteger'; -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeCeil = Math.ceil, - nativeIsFinite = root.isFinite; +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeCeil = Math.ceil; /** - * Creates the padding required for `string` based on the given `length`. - * The `chars` string is truncated if the number of characters exceeds `length`. + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. * * @private * @param {string} string The string to create padding for. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the pad for `string`. + * @returns {string} Returns the padding for `string`. */ function createPadding(string, length, chars) { - var strLength = string.length; - length = +length; + length = toInteger(length); - if (strLength >= length || !nativeIsFinite(length)) { + var strLength = stringSize(string); + if (!length || strLength >= length) { return ''; } var padLength = length - strLength; - chars = chars == null ? ' ' : (chars + ''); - return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + chars = chars === undefined ? ' ' : (chars + ''); + + var result = repeat(chars, nativeCeil(padLength / stringSize(chars))); + return reHasComplexSymbol.test(chars) + ? stringToArray(result).slice(0, padLength).join('') + : result.slice(0, padLength); } export default createPadding; diff --git a/internal/createPartial.js b/internal/createPartial.js deleted file mode 100644 index fb268ade2..000000000 --- a/internal/createPartial.js +++ /dev/null @@ -1,20 +0,0 @@ -import createWrapper from './createWrapper'; -import replaceHolders from './replaceHolders'; -import restParam from '../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, undefined, partials, holders); - }); - return partialFunc; -} - -export default createPartial; diff --git a/internal/createPartialWrapper.js b/internal/createPartialWrapper.js index f9635fc02..42e2b0d67 100644 --- a/internal/createPartialWrapper.js +++ b/internal/createPartialWrapper.js @@ -1,3 +1,4 @@ +import apply from './apply'; import createCtorWrapper from './createCtorWrapper'; import root from './root'; @@ -5,29 +6,28 @@ import root from './root'; var BIND_FLAG = 1; /** - * Creates a function that wraps `func` and invokes it with the optional `this` + * Creates a function that wraps `func` to invoke it with the optional `this` * binding of `thisArg` and the `partials` prepended to those provided to * the wrapper. * * @private - * @param {Function} func The function to partially apply arguments to. - * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. * @param {*} thisArg The `this` binding of `func`. * @param {Array} partials The arguments to prepend to those provided to the new function. - * @returns {Function} Returns the new bound function. + * @returns {Function} Returns the new wrapped function. */ function createPartialWrapper(func, bitmask, thisArg, partials) { var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { - // Avoid `arguments` object use disqualifying optimizations by - // converting it to an array before providing it `func`. var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, - args = Array(leftLength + argsLength); + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; @@ -35,8 +35,7 @@ function createPartialWrapper(func, bitmask, thisArg, partials) { while (argsLength--) { args[leftIndex++] = arguments[++argsIndex]; } - var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; - return fn.apply(isBind ? thisArg : this, args); + return apply(fn, isBind ? thisArg : this, args); } return wrapper; } diff --git a/internal/createRange.js b/internal/createRange.js new file mode 100644 index 000000000..b26c7670c --- /dev/null +++ b/internal/createRange.js @@ -0,0 +1,31 @@ +import baseRange from './baseRange'; +import isIterateeCall from './isIterateeCall'; +import toNumber from '../toNumber'; + +/** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ +function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toNumber(start); + start = start === start ? start : 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = toNumber(end) || 0; + } + step = step === undefined ? (start < end ? 1 : -1) : (toNumber(step) || 0); + return baseRange(start, end, step, fromRight); + }; +} + +export default createRange; diff --git a/internal/createRecurryWrapper.js b/internal/createRecurryWrapper.js new file mode 100644 index 000000000..127dfdb9a --- /dev/null +++ b/internal/createRecurryWrapper.js @@ -0,0 +1,53 @@ +import copyArray from './copyArray'; +import isLaziable from './isLaziable'; +import setData from './setData'; + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64; + +/** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder to replace. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & CURRY_FLAG, + newArgPos = argPos ? copyArray(argPos) : undefined, + newsHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!(bitmask & CURRY_BOUND_FLAG)) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, arity], + result = wrapFunc.apply(undefined, newData); + + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; +} + +export default createRecurryWrapper; diff --git a/internal/createReduce.js b/internal/createReduce.js deleted file mode 100644 index 66c99fde2..000000000 --- a/internal/createReduce.js +++ /dev/null @@ -1,22 +0,0 @@ -import baseCallback from './baseCallback'; -import baseReduce from './baseReduce'; -import isArray from '../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' && thisArg === undefined && isArray(collection)) - ? arrayFunc(collection, iteratee, accumulator, initFromArray) - : baseReduce(collection, baseCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); - }; -} - -export default createReduce; diff --git a/internal/createRound.js b/internal/createRound.js index 27a759f2a..a197b70e2 100644 --- a/internal/createRound.js +++ b/internal/createRound.js @@ -1,8 +1,9 @@ -/** Native method references. */ -var pow = Math.pow; +import toInteger from '../toInteger'; +import toNumber from '../toNumber'; +import toString from '../toString'; /** - * Creates a `_.ceil`, `_.floor`, or `_.round` function. + * Creates a function like `_.round`. * * @private * @param {string} methodName The name of the `Math` method to use when rounding. @@ -11,10 +12,16 @@ var pow = Math.pow; function createRound(methodName) { var func = Math[methodName]; return function(number, precision) { - precision = precision === undefined ? 0 : (+precision || 0); + number = toNumber(number); + precision = toInteger(precision); if (precision) { - precision = pow(10, precision); - return func(number * precision) / precision; + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); } return func(number); }; diff --git a/internal/createSet.js b/internal/createSet.js new file mode 100644 index 000000000..63536c8d8 --- /dev/null +++ b/internal/createSet.js @@ -0,0 +1,15 @@ +import Set from './Set'; +import noop from '../noop'; + +/** + * Creates a set of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ +var createSet = !(Set && new Set([1, 2]).size === 2) ? noop : function(values) { + return new Set(values); +}; + +export default createSet; diff --git a/internal/createSortedIndex.js b/internal/createSortedIndex.js deleted file mode 100644 index b7807bba0..000000000 --- a/internal/createSortedIndex.js +++ /dev/null @@ -1,20 +0,0 @@ -import baseCallback from './baseCallback'; -import binaryIndex from './binaryIndex'; -import binaryIndexBy from './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); - }; -} - -export default createSortedIndex; diff --git a/internal/createWrapper.js b/internal/createWrapper.js index bc4d6eacf..e5ba76744 100644 --- a/internal/createWrapper.js +++ b/internal/createWrapper.js @@ -1,21 +1,25 @@ import baseSetData from './baseSetData'; -import createBindWrapper from './createBindWrapper'; +import createBaseWrapper from './createBaseWrapper'; +import createCurryWrapper from './createCurryWrapper'; import createHybridWrapper from './createHybridWrapper'; import createPartialWrapper from './createPartialWrapper'; import getData from './getData'; import mergeData from './mergeData'; import setData from './setData'; +import toInteger from '../toInteger'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, + CURRY_FLAG = 8, + CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64; /** 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. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; /** @@ -23,8 +27,8 @@ var nativeMax = Math.max; * `this` binding and partially applied arguments. * * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of flags. + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask of wrapper flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` @@ -53,7 +57,10 @@ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, a bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); partials = holders = undefined; } - length -= (holders ? holders.length : 0); + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; @@ -65,17 +72,25 @@ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, a if (data) { mergeData(newData, data); - bitmask = newData[1]; - arity = newData[9]; } - newData[9] = arity == null + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] == null ? (isBindKey ? 0 : func.length) - : (nativeMax(arity - length, 0) || 0); + : nativeMax(newData[9] - length, 0); - if (bitmask == BIND_FLAG) { - var result = createBindWrapper(newData[0], newData[2]); - } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { - result = createPartialWrapper.apply(undefined, newData); + if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) { + bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == BIND_FLAG) { + var result = createBaseWrapper(func, bitmask, thisArg); + } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) { + result = createCurryWrapper(func, bitmask, arity); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) { + result = createPartialWrapper(func, bitmask, thisArg, partials); } else { result = createHybridWrapper.apply(undefined, newData); } diff --git a/internal/equalArrays.js b/internal/equalArrays.js index f94e2f3e4..76f8f302b 100644 --- a/internal/equalArrays.js +++ b/internal/equalArrays.js @@ -1,5 +1,9 @@ import arraySome from './arraySome'; +/** Used to compose bitmasks for comparison styles. */ +var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; + /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. @@ -8,44 +12,61 @@ import arraySome from './arraySome'; * @param {Array} array The array to compare. * @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} [isLoose] Specify performing partial comparisons. - * @param {Array} [stackA] Tracks traversed `value` objects. - * @param {Array} [stackB] Tracks traversed `other` objects. + * @param {Function} [customizer] The function to customize comparisons. + * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. + * @param {Object} [stack] Tracks traversed `array` and `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ -function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { +function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { var index = -1, + isPartial = bitmask & PARTIAL_COMPARE_FLAG, + isUnordered = bitmask & UNORDERED_COMPARE_FLAG, arrLength = array.length, othLength = other.length; - if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { return false; } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked) { + return stacked == other; + } + var result = true; + stack.set(array, other); + // Ignore non-index properties. while (++index < arrLength) { var arrValue = array[index], - othValue = other[index], - result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + othValue = other[index]; - if (result !== undefined) { - if (result) { + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { continue; } - return false; + result = false; + break; } // Recursively compare arrays (susceptible to call stack limits). - if (isLoose) { + if (isUnordered) { if (!arraySome(other, function(othValue) { - return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack); })) { - return false; + result = false; + break; } - } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { - return false; + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { + result = false; + break; } } - return true; + stack['delete'](array); + return result; } export default equalArrays; diff --git a/internal/equalByTag.js b/internal/equalByTag.js index 8fa010411..2a1355eb2 100644 --- a/internal/equalByTag.js +++ b/internal/equalByTag.js @@ -1,10 +1,28 @@ +import Uint8Array from './Uint8Array'; +import _Symbol from './_Symbol'; +import mapToArray from './mapToArray'; +import setToArray from './setToArray'; + +/** Used to compose bitmasks for comparison styles. */ +var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; + /** `Object#toString` result references. */ var boolTag = '[object Boolean]', dateTag = '[object Date]', errorTag = '[object Error]', + mapTag = '[object Map]', numberTag = '[object Number]', regexpTag = '[object RegExp]', - stringTag = '[object String]'; + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = _Symbol ? _Symbol.prototype : undefined, + symbolValueOf = _Symbol ? symbolProto.valueOf : undefined; /** * A specialized version of `baseIsEqualDeep` for comparing objects of @@ -17,10 +35,20 @@ var boolTag = '[object Boolean]', * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparisons. + * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -function equalByTag(object, other, tag) { +function equalByTag(object, other, tag, equalFunc, customizer, bitmask) { switch (tag) { + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + case boolTag: case dateTag: // Coerce dates and booleans to numbers, dates to milliseconds and booleans @@ -32,15 +60,27 @@ function equalByTag(object, other, tag) { case numberTag: // Treat `NaN` vs. `NaN` as equal. - return (object != +object) - ? other != +other - : object == +other; + return (object != +object) ? other != +other : object == +other; case regexpTag: case stringTag: // Coerce regexes to strings and treat strings primitives and string // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & PARTIAL_COMPARE_FLAG; + convert || (convert = setToArray); + + // Recursively compare objects (susceptible to call stack limits). + return (isPartial || object.size == other.size) && + equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG); + + case symbolTag: + return !!_Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); } return false; } diff --git a/internal/equalObjects.js b/internal/equalObjects.js index cbae5d662..a98567ce8 100644 --- a/internal/equalObjects.js +++ b/internal/equalObjects.js @@ -1,10 +1,9 @@ -import keys from '../object/keys'; +import baseHas from './baseHas'; +import keys from '../keys'; -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; +/** Used to compose bitmasks for comparison styles. */ +var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; /** * A specialized version of `baseIsEqualDeep` for objects with support for @@ -14,42 +13,60 @@ var hasOwnProperty = objectProto.hasOwnProperty; * @param {Object} object The object to compare. * @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} [isLoose] Specify performing partial comparisons. - * @param {Array} [stackA] Tracks traversed `value` objects. - * @param {Array} [stackB] Tracks traversed `other` objects. + * @param {Function} [customizer] The function to customize comparisons. + * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ -function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { - var objProps = keys(object), +function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG, + isUnordered = bitmask & UNORDERED_COMPARE_FLAG, + objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; - if (objLength != othLength && !isLoose) { + if (objLength != othLength && !isPartial) { return false; } var index = objLength; while (index--) { var key = objProps[index]; - if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + if (!(isPartial ? key in other : baseHas(other, key)) || + !(isUnordered || key == othProps[index])) { return false; } } - var skipCtor = isLoose; + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + var result = true; + stack.set(object, other); + + var skipCtor = isPartial; while (++index < objLength) { key = objProps[index]; var objValue = object[key], - othValue = other[key], - result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined; + othValue = other[key]; + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } // Recursively compare objects (susceptible to call stack limits). - if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { - return false; + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) + : compared + )) { + result = false; + break; } skipCtor || (skipCtor = key == 'constructor'); } - if (!skipCtor) { + if (result && !skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; @@ -58,10 +75,11 @@ function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, sta ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { - return false; + result = false; } } - return true; + stack['delete'](object); + return result; } export default equalObjects; diff --git a/internal/escapeRegExpChar.js b/internal/escapeRegExpChar.js deleted file mode 100644 index 625ab38d0..000000000 --- a/internal/escapeRegExpChar.js +++ /dev/null @@ -1,38 +0,0 @@ -/** Used to escape characters for inclusion in compiled regexes. */ -var regexpEscapes = { - '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34', - '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39', - 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46', - 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66', - 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78' -}; - -/** Used to escape characters for inclusion in compiled string literals. */ -var stringEscapes = { - '\\': '\\', - "'": "'", - '\n': 'n', - '\r': 'r', - '\u2028': 'u2028', - '\u2029': 'u2029' -}; - -/** - * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes. - * - * @private - * @param {string} chr The matched character to escape. - * @param {string} leadingChar The capture group for a leading character. - * @param {string} whitespaceChar The capture group for a whitespace character. - * @returns {string} Returns the escaped character. - */ -function escapeRegExpChar(chr, leadingChar, whitespaceChar) { - if (leadingChar) { - chr = regexpEscapes[chr]; - } else if (whitespaceChar) { - chr = stringEscapes[chr]; - } - return '\\' + chr; -} - -export default escapeRegExpChar; diff --git a/internal/getData.js b/internal/getData.js index 7dc75375a..ab01f2379 100644 --- a/internal/getData.js +++ b/internal/getData.js @@ -1,5 +1,5 @@ import metaMap from './metaMap'; -import noop from '../utility/noop'; +import noop from '../noop'; /** * Gets metadata for `func`. diff --git a/internal/getMatchData.js b/internal/getMatchData.js index bccf3c31e..bb5124708 100644 --- a/internal/getMatchData.js +++ b/internal/getMatchData.js @@ -1,15 +1,15 @@ import isStrictComparable from './isStrictComparable'; -import pairs from '../object/pairs'; +import toPairs from '../toPairs'; /** - * Gets the propery names, values, and compare flags of `object`. + * Gets the property names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { - var result = pairs(object), + var result = toPairs(object), length = result.length; while (length--) { diff --git a/internal/getNative.js b/internal/getNative.js index 099a9b379..1b8e71391 100644 --- a/internal/getNative.js +++ b/internal/getNative.js @@ -1,4 +1,4 @@ -import isNative from '../lang/isNative'; +import isNative from '../isNative'; /** * Gets the native function at `key` of `object`. diff --git a/internal/getSymbols.js b/internal/getSymbols.js new file mode 100644 index 000000000..73bbca717 --- /dev/null +++ b/internal/getSymbols.js @@ -0,0 +1,15 @@ +/** Built-in value references. */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own symbol properties of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = getOwnPropertySymbols || function() { + return []; +}; + +export default getSymbols; diff --git a/internal/getTag.js b/internal/getTag.js new file mode 100644 index 000000000..3ecf91703 --- /dev/null +++ b/internal/getTag.js @@ -0,0 +1,55 @@ +import Map from './Map'; +import Set from './Set'; + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + objectTag = '[object Object]', + setTag = '[object Set]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = Function.prototype.toString; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Used to detect maps and sets. */ +var mapCtorString = Map ? funcToString.call(Map) : '', + setCtorString = Set ? funcToString.call(Set) : ''; + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function getTag(value) { + return objectToString.call(value); +} + +// Fallback for IE 11 providing `toStringTag` values for maps and sets. +if ((Map && getTag(new Map) != mapTag) || (Set && getTag(new Set) != setTag)) { + getTag = function(value) { + var result = objectToString.call(value), + Ctor = result == objectTag ? value.constructor : null, + ctorString = typeof Ctor == 'function' ? funcToString.call(Ctor) : ''; + + if (ctorString) { + if (ctorString == mapCtorString) { + return mapTag; + } + if (ctorString == setCtorString) { + return setTag; + } + } + return result; + }; +} + +export default getTag; diff --git a/internal/getView.js b/internal/getView.js index cf677bf13..14fbba4d8 100644 --- a/internal/getView.js +++ b/internal/getView.js @@ -1,4 +1,4 @@ -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max, nativeMin = Math.min; diff --git a/internal/hasPath.js b/internal/hasPath.js new file mode 100644 index 000000000..66dd47845 --- /dev/null +++ b/internal/hasPath.js @@ -0,0 +1,37 @@ +import baseToPath from './baseToPath'; +import isArguments from '../isArguments'; +import isArray from '../isArray'; +import isIndex from './isIndex'; +import isKey from './isKey'; +import isLength from '../isLength'; +import isString from '../isString'; +import last from '../last'; +import parent from './parent'; + +/** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ +function hasPath(object, path, hasFunc) { + if (object == null) { + return false; + } + var result = hasFunc(object, path); + if (!result && !isKey(path)) { + path = baseToPath(path); + object = parent(object, path); + if (object != null) { + path = last(path); + result = hasFunc(object, path); + } + } + return result || (isLength(object && object.length) && isIndex(path, object.length) && + (isArray(object) || isString(object) || isArguments(object))); +} + +export default hasPath; diff --git a/internal/hashDelete.js b/internal/hashDelete.js new file mode 100644 index 000000000..28a88c4fb --- /dev/null +++ b/internal/hashDelete.js @@ -0,0 +1,15 @@ +import hashHas from './hashHas'; + +/** + * Removes `key` and its value from the hash. + * + * @private + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(hash, key) { + return hashHas(hash, key) && delete hash[key]; +} + +export default hashDelete; diff --git a/internal/hashGet.js b/internal/hashGet.js new file mode 100644 index 000000000..72557a1c5 --- /dev/null +++ b/internal/hashGet.js @@ -0,0 +1,28 @@ +import nativeCreate from './nativeCreate'; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @param {Object} hash The hash to query. + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(hash, key) { + if (nativeCreate) { + var result = hash[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(hash, key) ? hash[key] : undefined; +} + +export default hashGet; diff --git a/internal/hashHas.js b/internal/hashHas.js new file mode 100644 index 000000000..90e74a178 --- /dev/null +++ b/internal/hashHas.js @@ -0,0 +1,21 @@ +import nativeCreate from './nativeCreate'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @param {Object} hash The hash to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(hash, key) { + return nativeCreate ? hash[key] !== undefined : hasOwnProperty.call(hash, key); +} + +export default hashHas; diff --git a/internal/hashSet.js b/internal/hashSet.js new file mode 100644 index 000000000..d2d0738ee --- /dev/null +++ b/internal/hashSet.js @@ -0,0 +1,18 @@ +import nativeCreate from './nativeCreate'; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + */ +function hashSet(hash, key, value) { + hash[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; +} + +export default hashSet; diff --git a/internal/indexKeys.js b/internal/indexKeys.js new file mode 100644 index 000000000..070f4e68d --- /dev/null +++ b/internal/indexKeys.js @@ -0,0 +1,22 @@ +import baseTimes from './baseTimes'; +import isArguments from '../isArguments'; +import isArray from '../isArray'; +import isLength from '../isLength'; +import isString from '../isString'; + +/** + * Creates an array of index keys for `object` values of arrays, + * `arguments` objects, and strings, otherwise `null` is returned. + * + * @private + * @param {Object} object The object to query. + * @returns {Array|null} Returns index keys, else `null`. + */ +function indexKeys(object) { + var length = object ? object.length : undefined; + return (isLength(length) && (isArray(object) || isString(object) || isArguments(object))) + ? baseTimes(length, String) + : null; +} + +export default indexKeys; diff --git a/internal/initCloneArray.js b/internal/initCloneArray.js index 8e6d68296..599732e03 100644 --- a/internal/initCloneArray.js +++ b/internal/initCloneArray.js @@ -1,4 +1,4 @@ -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to check objects for own properties. */ @@ -13,9 +13,9 @@ var hasOwnProperty = objectProto.hasOwnProperty; */ function initCloneArray(array) { var length = array.length, - result = new array.constructor(length); + result = array.constructor(length); - // Add array properties assigned by `RegExp#exec`. + // Add properties assigned by `RegExp#exec`. if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { result.index = array.index; result.input = array.input; diff --git a/internal/initCloneByTag.js b/internal/initCloneByTag.js index 3751a36e5..bf02b3577 100644 --- a/internal/initCloneByTag.js +++ b/internal/initCloneByTag.js @@ -1,11 +1,19 @@ -import bufferClone from './bufferClone'; +import cloneBuffer from './cloneBuffer'; +import cloneMap from './cloneMap'; +import cloneRegExp from './cloneRegExp'; +import cloneSet from './cloneSet'; +import cloneSymbol from './cloneSymbol'; +import cloneTypedArray from './cloneTypedArray'; /** `Object#toString` result references. */ var boolTag = '[object Boolean]', dateTag = '[object Date]', + mapTag = '[object Map]', numberTag = '[object Number]', regexpTag = '[object RegExp]', - stringTag = '[object String]'; + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; var arrayBufferTag = '[object ArrayBuffer]', float32Tag = '[object Float32Array]', @@ -18,9 +26,6 @@ var arrayBufferTag = '[object ArrayBuffer]', uint16Tag = '[object Uint16Array]', uint32Tag = '[object Uint32Array]'; -/** Used to match `RegExp` flags from their coerced string values. */ -var reFlags = /\w*$/; - /** * Initializes an object clone based on its `toStringTag`. * @@ -37,7 +42,7 @@ function initCloneByTag(object, tag, isDeep) { var Ctor = object.constructor; switch (tag) { case arrayBufferTag: - return bufferClone(object); + return cloneBuffer(object); case boolTag: case dateTag: @@ -46,18 +51,24 @@ function initCloneByTag(object, tag, isDeep) { case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: - var buffer = object.buffer; - return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + return cloneTypedArray(object, isDeep); + + case mapTag: + return cloneMap(object); case numberTag: case stringTag: return new Ctor(object); case regexpTag: - var result = new Ctor(object.source, reFlags.exec(object)); - result.lastIndex = object.lastIndex; + return cloneRegExp(object); + + case setTag: + return cloneSet(object); + + case symbolTag: + return cloneSymbol(object); } - return result; } export default initCloneByTag; diff --git a/internal/initCloneObject.js b/internal/initCloneObject.js index 5d8afa206..40f5fa485 100644 --- a/internal/initCloneObject.js +++ b/internal/initCloneObject.js @@ -1,3 +1,6 @@ +import baseCreate from './baseCreate'; +import isFunction from '../isFunction'; + /** * Initializes an object clone. * @@ -7,10 +10,7 @@ */ function initCloneObject(object) { var Ctor = object.constructor; - if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) { - Ctor = Object; - } - return new Ctor; + return baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); } export default initCloneObject; diff --git a/internal/invokePath.js b/internal/invokePath.js deleted file mode 100644 index 1aee55a25..000000000 --- a/internal/invokePath.js +++ /dev/null @@ -1,26 +0,0 @@ -import baseGet from './baseGet'; -import baseSlice from './baseSlice'; -import isKey from './isKey'; -import last from '../array/last'; -import toPath from './toPath'; - -/** - * Invokes the method at `path` on `object`. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the method to invoke. - * @param {Array} args The arguments to invoke the method with. - * @returns {*} Returns the result of the invoked method. - */ -function invokePath(object, path, args) { - if (object != null && !isKey(path, object)) { - path = toPath(path); - object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); - path = last(path); - } - var func = object == null ? object : object[path]; - return func == null ? undefined : func.apply(object, args); -} - -export default invokePath; diff --git a/internal/isArrayLike.js b/internal/isArrayLike.js deleted file mode 100644 index df01faef9..000000000 --- a/internal/isArrayLike.js +++ /dev/null @@ -1,15 +0,0 @@ -import getLength from './getLength'; -import isLength from './isLength'; - -/** - * Checks if `value` is array-like. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - */ -function isArrayLike(value) { - return value != null && isLength(getLength(value)); -} - -export default isArrayLike; diff --git a/internal/isHostObject.js b/internal/isHostObject.js new file mode 100644 index 000000000..29382d12f --- /dev/null +++ b/internal/isHostObject.js @@ -0,0 +1,20 @@ +/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ +function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) {} + } + return result; +} + +export default isHostObject; diff --git a/internal/isIndex.js b/internal/isIndex.js index 8bbc020d9..47a4460e5 100644 --- a/internal/isIndex.js +++ b/internal/isIndex.js @@ -1,12 +1,9 @@ -/** Used to detect unsigned integer values. */ -var reIsUint = /^\d+$/; - -/** - * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) - * of an array-like value. - */ +/** Used as references for various `Number` constants. */ var MAX_SAFE_INTEGER = 9007199254740991; +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + /** * Checks if `value` is a valid array-like index. * diff --git a/internal/isIterateeCall.js b/internal/isIterateeCall.js index 4c85d77b1..808ad1345 100644 --- a/internal/isIterateeCall.js +++ b/internal/isIterateeCall.js @@ -1,6 +1,7 @@ -import isArrayLike from './isArrayLike'; +import eq from '../eq'; +import isArrayLike from '../isArrayLike'; import isIndex from './isIndex'; -import isObject from '../lang/isObject'; +import isObject from '../isObject'; /** * Checks if the provided arguments are from an iteratee call. @@ -19,8 +20,7 @@ function isIterateeCall(value, index, object) { if (type == 'number' ? (isArrayLike(object) && isIndex(index, object.length)) : (type == 'string' && index in object)) { - var other = object[index]; - return value === value ? (value === other) : (other !== other); + return eq(object[index], value); } return false; } diff --git a/internal/isKey.js b/internal/isKey.js index 51345543f..76e0981eb 100644 --- a/internal/isKey.js +++ b/internal/isKey.js @@ -1,8 +1,7 @@ -import isArray from '../lang/isArray'; -import toObject from './toObject'; +import isArray from '../isArray'; /** Used to match property names within property paths. */ -var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/; /** @@ -14,15 +13,12 @@ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { - var type = typeof value; - if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') { + if (typeof value == 'number') { return true; } - if (isArray(value)) { - return false; - } - var result = !reIsDeepProp.test(value); - return result || (object != null && value in toObject(object)); + return !isArray(value) && + (reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object))); } export default isKey; diff --git a/internal/isKeyable.js b/internal/isKeyable.js new file mode 100644 index 000000000..972b86b62 --- /dev/null +++ b/internal/isKeyable.js @@ -0,0 +1,14 @@ +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return type == 'number' || type == 'boolean' || + (type == 'string' && value !== '__proto__') || value == null; +} + +export default isKeyable; diff --git a/internal/isLaziable.js b/internal/isLaziable.js index 5b588712a..feaac019b 100644 --- a/internal/isLaziable.js +++ b/internal/isLaziable.js @@ -1,7 +1,7 @@ import LazyWrapper from './LazyWrapper'; import getData from './getData'; import getFuncName from './getFuncName'; -import lodash from '../chain/lodash'; +import lodash from '../wrapperLodash'; /** * Checks if `func` has a lazy counterpart. diff --git a/internal/isLength.js b/internal/isLength.js deleted file mode 100644 index 717da4e97..000000000 --- a/internal/isLength.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) - * of an array-like value. - */ -var MAX_SAFE_INTEGER = 9007199254740991; - -/** - * Checks if `value` is a valid array-like length. - * - * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. - */ -function isLength(value) { - return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; -} - -export default isLength; diff --git a/internal/isObjectLike.js b/internal/isObjectLike.js deleted file mode 100644 index 3aab34860..000000000 --- a/internal/isObjectLike.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Checks if `value` is object-like. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - */ -function isObjectLike(value) { - return !!value && typeof value == 'object'; -} - -export default isObjectLike; diff --git a/internal/isPrototype.js b/internal/isPrototype.js new file mode 100644 index 000000000..f6c7660d0 --- /dev/null +++ b/internal/isPrototype.js @@ -0,0 +1,18 @@ +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +export default isPrototype; diff --git a/internal/isSpace.js b/internal/isSpace.js deleted file mode 100644 index b9082a212..000000000 --- a/internal/isSpace.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a - * character code is whitespace. - * - * @private - * @param {number} charCode The character code to inspect. - * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`. - */ -function isSpace(charCode) { - return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 || - (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279))); -} - -export default isSpace; diff --git a/internal/isStrictComparable.js b/internal/isStrictComparable.js index a3d21d21c..1d6ef1257 100644 --- a/internal/isStrictComparable.js +++ b/internal/isStrictComparable.js @@ -1,4 +1,4 @@ -import isObject from '../lang/isObject'; +import isObject from '../isObject'; /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. diff --git a/internal/iteratorToArray.js b/internal/iteratorToArray.js new file mode 100644 index 000000000..315bf2bfe --- /dev/null +++ b/internal/iteratorToArray.js @@ -0,0 +1,18 @@ +/** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ +function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; +} + +export default iteratorToArray; diff --git a/internal/lazyClone.js b/internal/lazyClone.js index 2169ceaf7..f000e864c 100644 --- a/internal/lazyClone.js +++ b/internal/lazyClone.js @@ -1,5 +1,5 @@ import LazyWrapper from './LazyWrapper'; -import arrayCopy from './arrayCopy'; +import copyArray from './copyArray'; /** * Creates a clone of the lazy wrapper object. @@ -11,12 +11,12 @@ import arrayCopy from './arrayCopy'; */ function lazyClone() { var result = new LazyWrapper(this.__wrapped__); - result.__actions__ = arrayCopy(this.__actions__); + result.__actions__ = copyArray(this.__actions__); result.__dir__ = this.__dir__; result.__filtered__ = this.__filtered__; - result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__iteratees__ = copyArray(this.__iteratees__); result.__takeCount__ = this.__takeCount__; - result.__views__ = arrayCopy(this.__views__); + result.__views__ = copyArray(this.__views__); return result; } diff --git a/internal/lazyValue.js b/internal/lazyValue.js index 9b6014d6b..93651a3f8 100644 --- a/internal/lazyValue.js +++ b/internal/lazyValue.js @@ -1,6 +1,6 @@ import baseWrapperValue from './baseWrapperValue'; import getView from './getView'; -import isArray from '../lang/isArray'; +import isArray from '../isArray'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; @@ -9,7 +9,7 @@ var LARGE_ARRAY_SIZE = 200; var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMin = Math.min; /** diff --git a/internal/mapClear.js b/internal/mapClear.js new file mode 100644 index 000000000..51e2918cb --- /dev/null +++ b/internal/mapClear.js @@ -0,0 +1,15 @@ +import Hash from './Hash'; +import Map from './Map'; + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapClear() { + this.__data__ = { 'hash': new Hash, 'map': Map ? new Map : [], 'string': new Hash }; +} + +export default mapClear; diff --git a/internal/mapDelete.js b/internal/mapDelete.js index 6fce95500..120f56cae 100644 --- a/internal/mapDelete.js +++ b/internal/mapDelete.js @@ -1,14 +1,23 @@ +import Map from './Map'; +import assocDelete from './assocDelete'; +import hashDelete from './hashDelete'; +import isKeyable from './isKeyable'; + /** - * Removes `key` and its value from the cache. + * Removes `key` and its value from the map. * * @private * @name delete - * @memberOf _.memoize.Cache + * @memberOf MapCache * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapDelete(key) { - return this.has(key) && delete this.__data__[key]; + var data = this.__data__; + if (isKeyable(key)) { + return hashDelete(typeof key == 'string' ? data.string : data.hash, key); + } + return Map ? data.map['delete'](key) : assocDelete(data.map, key); } export default mapDelete; diff --git a/internal/mapGet.js b/internal/mapGet.js index 4f1913dec..1aaeda84f 100644 --- a/internal/mapGet.js +++ b/internal/mapGet.js @@ -1,14 +1,23 @@ +import Map from './Map'; +import assocGet from './assocGet'; +import hashGet from './hashGet'; +import isKeyable from './isKeyable'; + /** - * Gets the cached value for `key`. + * Gets the map value for `key`. * * @private * @name get - * @memberOf _.memoize.Cache + * @memberOf MapCache * @param {string} key The key of the value to get. - * @returns {*} Returns the cached value. + * @returns {*} Returns the entry value. */ function mapGet(key) { - return key == '__proto__' ? undefined : this.__data__[key]; + var data = this.__data__; + if (isKeyable(key)) { + return hashGet(typeof key == 'string' ? data.string : data.hash, key); + } + return Map ? data.map.get(key) : assocGet(data.map, key); } export default mapGet; diff --git a/internal/mapHas.js b/internal/mapHas.js index 0bea8caae..2bbcd7a99 100644 --- a/internal/mapHas.js +++ b/internal/mapHas.js @@ -1,20 +1,23 @@ -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; +import Map from './Map'; +import assocHas from './assocHas'; +import hashHas from './hashHas'; +import isKeyable from './isKeyable'; /** - * Checks if a cached value for `key` exists. + * Checks if a map value for `key` exists. * * @private * @name has - * @memberOf _.memoize.Cache + * @memberOf MapCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function mapHas(key) { - return key != '__proto__' && hasOwnProperty.call(this.__data__, key); + var data = this.__data__; + if (isKeyable(key)) { + return hashHas(typeof key == 'string' ? data.string : data.hash, key); + } + return Map ? data.map.has(key) : assocHas(data.map, key); } export default mapHas; diff --git a/internal/mapSet.js b/internal/mapSet.js index 90bd28aee..5bc650a56 100644 --- a/internal/mapSet.js +++ b/internal/mapSet.js @@ -1,16 +1,26 @@ +import Map from './Map'; +import assocSet from './assocSet'; +import hashSet from './hashSet'; +import isKeyable from './isKeyable'; + /** - * Sets `value` to `key` of the cache. + * Sets the map `key` to `value`. * * @private * @name set - * @memberOf _.memoize.Cache - * @param {string} key The key of the value to cache. - * @param {*} value The value to cache. - * @returns {Object} Returns the cache object. + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache object. */ function mapSet(key, value) { - if (key != '__proto__') { - this.__data__[key] = value; + var data = this.__data__; + if (isKeyable(key)) { + hashSet(typeof key == 'string' ? data.string : data.hash, key, value); + } else if (Map) { + data.map.set(key, value); + } else { + assocSet(data.map, key, value); } return this; } diff --git a/internal/mapToArray.js b/internal/mapToArray.js new file mode 100644 index 000000000..fd5adc419 --- /dev/null +++ b/internal/mapToArray.js @@ -0,0 +1,18 @@ +/** + * Converts `map` to an array. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the converted array. + */ +function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +export default mapToArray; diff --git a/internal/mergeData.js b/internal/mergeData.js index 156398383..0dda6e78c 100644 --- a/internal/mergeData.js +++ b/internal/mergeData.js @@ -1,10 +1,11 @@ -import arrayCopy from './arrayCopy'; import composeArgs from './composeArgs'; import composeArgsRight from './composeArgsRight'; +import copyArray from './copyArray'; import replaceHolders from './replaceHolders'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, ARY_FLAG = 128, @@ -13,18 +14,18 @@ var BIND_FLAG = 1, /** Used as the internal argument placeholder. */ var PLACEHOLDER = '__lodash_placeholder__'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMin = Math.min; /** * Merges the function metadata of `source` into `data`. * - * Merging metadata reduces the number of wrappers required to invoke a function. + * Merging metadata reduces the number of wrappers used to invoke a function. * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` - * augment function arguments, making the order in which they are executed important, + * modify function arguments, making the order in which they are executed important, * preventing the merging of metadata. However, we make an exception for a safe - * common case where curried functions have `_.ary` and or `_.rearg` applied. + * combined case where curried functions have `_.ary` and or `_.rearg` applied. * * @private * @param {Array} data The destination metadata. @@ -35,12 +36,12 @@ function mergeData(data, source) { var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, - isCommon = newBitmask < ARY_FLAG; + isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG); 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); + (srcBitmask == ARY_FLAG && (bitmask == CURRY_FLAG)) || + (srcBitmask == ARY_FLAG && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) || + (srcBitmask == (ARY_FLAG | REARG_FLAG) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG)); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { @@ -56,20 +57,20 @@ function mergeData(data, source) { var value = source[3]; if (value) { var partials = data[3]; - data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); - data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + data[3] = partials ? composeArgs(partials, value, source[4]) : copyArray(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : copyArray(source[4]); } // Compose partial right arguments. value = source[5]; if (value) { partials = data[5]; - data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); - data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + data[5] = partials ? composeArgsRight(partials, value, source[6]) : copyArray(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : copyArray(source[6]); } // Use source `argPos` if available. value = source[7]; if (value) { - data[7] = arrayCopy(value); + data[7] = copyArray(value); } // Use source `ary` if it's smaller. if (srcBitmask & ARY_FLAG) { diff --git a/internal/mergeDefaults.js b/internal/mergeDefaults.js index f9227ea86..9b74d4ea1 100644 --- a/internal/mergeDefaults.js +++ b/internal/mergeDefaults.js @@ -1,15 +1,25 @@ -import merge from '../object/merge'; +import baseClone from './baseClone'; +import baseMerge from './baseMerge'; +import isObject from '../isObject'; /** * Used by `_.defaultsDeep` to customize its `_.merge` use. * * @private - * @param {*} objectValue The destination object property value. - * @param {*} sourceValue The source object property value. - * @returns {*} Returns the value to assign to the destination object. + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged counterparts. + * @returns {*} Returns the value to assign. */ -function mergeDefaults(objectValue, sourceValue) { - return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); +function mergeDefaults(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, mergeDefaults, stack); + } + return objValue === undefined ? baseClone(srcValue) : objValue; } export default mergeDefaults; diff --git a/internal/metaMap.js b/internal/metaMap.js index 0b1d71119..aeda1e383 100644 --- a/internal/metaMap.js +++ b/internal/metaMap.js @@ -1,8 +1,4 @@ -import getNative from './getNative'; -import root from './root'; - -/** Native method references. */ -var WeakMap = getNative(root, 'WeakMap'); +import WeakMap from './WeakMap'; /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; diff --git a/internal/nativeCreate.js b/internal/nativeCreate.js new file mode 100644 index 000000000..1df596f45 --- /dev/null +++ b/internal/nativeCreate.js @@ -0,0 +1,6 @@ +import getNative from './getNative'; + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +export default nativeCreate; diff --git a/internal/parent.js b/internal/parent.js new file mode 100644 index 000000000..0f621956a --- /dev/null +++ b/internal/parent.js @@ -0,0 +1,16 @@ +import baseSlice from './baseSlice'; +import get from '../get'; + +/** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ +function parent(object, path) { + return path.length == 1 ? object : get(object, baseSlice(path, 0, -1)); +} + +export default parent; diff --git a/internal/pickByArray.js b/internal/pickByArray.js deleted file mode 100644 index 928932e5a..000000000 --- a/internal/pickByArray.js +++ /dev/null @@ -1,28 +0,0 @@ -import toObject from './toObject'; - -/** - * A specialized version of `_.pick` which picks `object` properties specified - * by `props`. - * - * @private - * @param {Object} object The source object. - * @param {string[]} props The property names to pick. - * @returns {Object} Returns the new object. - */ -function pickByArray(object, props) { - object = toObject(object); - - var index = -1, - length = props.length, - result = {}; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - return result; -} - -export default pickByArray; diff --git a/internal/pickByCallback.js b/internal/pickByCallback.js deleted file mode 100644 index a8af9550d..000000000 --- a/internal/pickByCallback.js +++ /dev/null @@ -1,22 +0,0 @@ -import baseForIn from './baseForIn'; - -/** - * A specialized version of `_.pick` which picks `object` properties `predicate` - * returns truthy for. - * - * @private - * @param {Object} object The source object. - * @param {Function} predicate The function invoked per iteration. - * @returns {Object} Returns the new object. - */ -function pickByCallback(object, predicate) { - var result = {}; - baseForIn(object, function(value, key, object) { - if (predicate(value, key, object)) { - result[key] = value; - } - }); - return result; -} - -export default pickByCallback; diff --git a/internal/reorder.js b/internal/reorder.js index a31e032cc..0be0bcebc 100644 --- a/internal/reorder.js +++ b/internal/reorder.js @@ -1,7 +1,7 @@ -import arrayCopy from './arrayCopy'; +import copyArray from './copyArray'; import isIndex from './isIndex'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMin = Math.min; /** @@ -17,7 +17,7 @@ var nativeMin = Math.min; function reorder(array, indexes) { var arrLength = array.length, length = nativeMin(indexes.length, arrLength), - oldArray = arrayCopy(array); + oldArray = copyArray(array); while (length--) { var index = indexes[length]; diff --git a/internal/root.js b/internal/root.js index 20d53b67d..2b376d78b 100644 --- a/internal/root.js +++ b/internal/root.js @@ -1,3 +1,5 @@ +import checkGlobal from './checkGlobal'; + /** Used to determine if values are of the language type `Object`. */ var objectTypes = { 'function': true, @@ -5,19 +7,22 @@ var objectTypes = { }; /** Detect free variable `exports`. */ -var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; +var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null; /** Detect free variable `module`. */ -var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; +var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null; /** Detect free variable `global` from Node.js. */ -var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global; +var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); /** Detect free variable `self`. */ -var freeSelf = objectTypes[typeof self] && self && self.Object && self; +var freeSelf = checkGlobal(objectTypes[typeof self] && self); /** Detect free variable `window`. */ -var freeWindow = objectTypes[typeof window] && window && window.Object && window; +var freeWindow = checkGlobal(objectTypes[typeof window] && window); + +/** Detect `this` as the global object. */ +var thisGlobal = checkGlobal(objectTypes[typeof this] && this); /** * Used as a reference to the global object. @@ -25,6 +30,6 @@ var freeWindow = objectTypes[typeof window] && window && window.Object && window * The `this` value is used if it's the global object to avoid Greasemonkey's * restricted `window` object, otherwise the `window` object is used. */ -var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this; +var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')(); export default root; diff --git a/internal/setData.js b/internal/setData.js index 6bc08bbd1..458127454 100644 --- a/internal/setData.js +++ b/internal/setData.js @@ -1,7 +1,7 @@ import baseSetData from './baseSetData'; -import now from '../date/now'; +import now from '../now'; -/** Used to detect when a function becomes hot. */ +/** Used to detect hot functions by number of calls within a span of milliseconds. */ var HOT_COUNT = 150, HOT_SPAN = 16; diff --git a/internal/setToArray.js b/internal/setToArray.js new file mode 100644 index 000000000..7ab0451dd --- /dev/null +++ b/internal/setToArray.js @@ -0,0 +1,18 @@ +/** + * Converts `set` to an array. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the converted array. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +export default setToArray; diff --git a/internal/shimKeys.js b/internal/shimKeys.js deleted file mode 100644 index fd7351231..000000000 --- a/internal/shimKeys.js +++ /dev/null @@ -1,41 +0,0 @@ -import isArguments from '../lang/isArguments'; -import isArray from '../lang/isArray'; -import isIndex from './isIndex'; -import isLength from './isLength'; -import keysIn from '../object/keysIn'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * A fallback implementation of `Object.keys` which creates an array of the - * own enumerable property names of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ -function shimKeys(object) { - var props = keysIn(object), - propsLength = props.length, - length = propsLength && object.length; - - var allowIndexes = !!length && isLength(length) && - (isArray(object) || isArguments(object)); - - var index = -1, - result = []; - - while (++index < propsLength) { - var key = props[index]; - if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { - result.push(key); - } - } - return result; -} - -export default shimKeys; diff --git a/internal/sortedUniq.js b/internal/sortedUniq.js deleted file mode 100644 index d5b9464f4..000000000 --- a/internal/sortedUniq.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * An implementation of `_.uniq` optimized for sorted arrays without support - * for callback shorthands and `this` binding. - * - * @private - * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The function invoked per iteration. - * @returns {Array} Returns the new duplicate free array. - */ -function sortedUniq(array, iteratee) { - var seen, - index = -1, - length = array.length, - resIndex = -1, - result = []; - - while (++index < length) { - var value = array[index], - computed = iteratee ? iteratee(value, index, array) : value; - - if (!index || seen !== computed) { - seen = computed; - result[++resIndex] = value; - } - } - return result; -} - -export default sortedUniq; diff --git a/internal/stackClear.js b/internal/stackClear.js new file mode 100644 index 000000000..8e0c9c038 --- /dev/null +++ b/internal/stackClear.js @@ -0,0 +1,12 @@ +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = { 'array': [], 'map': null }; +} + +export default stackClear; diff --git a/internal/stackDelete.js b/internal/stackDelete.js new file mode 100644 index 000000000..c9bdeb80a --- /dev/null +++ b/internal/stackDelete.js @@ -0,0 +1,19 @@ +import assocDelete from './assocDelete'; + +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete(key) { + var data = this.__data__, + array = data.array; + + return array ? assocDelete(array, key) : data.map['delete'](key); +} + +export default stackDelete; diff --git a/internal/stackGet.js b/internal/stackGet.js new file mode 100644 index 000000000..0f512c012 --- /dev/null +++ b/internal/stackGet.js @@ -0,0 +1,19 @@ +import assocGet from './assocGet'; + +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + var data = this.__data__, + array = data.array; + + return array ? assocGet(array, key) : data.map.get(key); +} + +export default stackGet; diff --git a/internal/stackHas.js b/internal/stackHas.js new file mode 100644 index 000000000..db6f9c663 --- /dev/null +++ b/internal/stackHas.js @@ -0,0 +1,19 @@ +import assocHas from './assocHas'; + +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + var data = this.__data__, + array = data.array; + + return array ? assocHas(array, key) : data.map.has(key); +} + +export default stackHas; diff --git a/internal/stackSet.js b/internal/stackSet.js new file mode 100644 index 000000000..160e241b0 --- /dev/null +++ b/internal/stackSet.js @@ -0,0 +1,36 @@ +import MapCache from './MapCache'; +import assocSet from './assocSet'; + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache object. + */ +function stackSet(key, value) { + var data = this.__data__, + array = data.array; + + if (array) { + if (array.length < (LARGE_ARRAY_SIZE - 1)) { + assocSet(array, key, value); + } else { + data.array = null; + data.map = new MapCache(array); + } + } + var map = data.map; + if (map) { + map.set(key, value); + } + return this; +} + +export default stackSet; diff --git a/internal/stringSize.js b/internal/stringSize.js new file mode 100644 index 000000000..070656b34 --- /dev/null +++ b/internal/stringSize.js @@ -0,0 +1,45 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reComplexSymbol = RegExp(rsSymbol + rsSeq, 'g'); + +/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Gets the number of symbols in `string`. + * + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ +function stringSize(string) { + if (!(string && reHasComplexSymbol.test(string))) { + return string.length; + } + var result = reComplexSymbol.lastIndex = 0; + while (reComplexSymbol.test(string)) { + result++; + } + return result; +} + +export default stringSize; diff --git a/internal/stringToArray.js b/internal/stringToArray.js new file mode 100644 index 000000000..5a2c6047a --- /dev/null +++ b/internal/stringToArray.js @@ -0,0 +1,36 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reComplexSymbol = RegExp(rsSymbol + rsSeq, 'g'); + +/** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function stringToArray(string) { + return string.match(reComplexSymbol); +} + +export default stringToArray; diff --git a/internal/toPath.js b/internal/stringToPath.js similarity index 51% rename from internal/toPath.js rename to internal/stringToPath.js index 918a521f5..5269d7870 100644 --- a/internal/toPath.js +++ b/internal/stringToPath.js @@ -1,28 +1,24 @@ -import baseToString from './baseToString'; -import isArray from '../lang/isArray'; +import toString from '../toString'; /** Used to match property names within property paths. */ -var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g; /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; /** - * Converts `value` to property path array if it's not one. + * Converts `string` to a property path array. * * @private - * @param {*} value The value to process. + * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ -function toPath(value) { - if (isArray(value)) { - return value; - } +function stringToPath(string) { var result = []; - baseToString(value).replace(rePropName, function(match, number, quote, string) { + toString(string).replace(rePropName, function(match, number, quote, string) { result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); }); return result; } -export default toPath; +export default stringToPath; diff --git a/internal/toArrayLikeObject.js b/internal/toArrayLikeObject.js new file mode 100644 index 000000000..b9066b11d --- /dev/null +++ b/internal/toArrayLikeObject.js @@ -0,0 +1,14 @@ +import isArrayLikeObject from '../isArrayLikeObject'; + +/** + * Converts `value` to an array-like object if it's not one. + * + * @private + * @param {*} value The value to process. + * @returns {Array} Returns the array-like object. + */ +function toArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; +} + +export default toArrayLikeObject; diff --git a/internal/toFunction.js b/internal/toFunction.js new file mode 100644 index 000000000..199ee43e1 --- /dev/null +++ b/internal/toFunction.js @@ -0,0 +1,14 @@ +import identity from '../identity'; + +/** + * Converts `value` to a function if it's not one. + * + * @private + * @param {*} value The value to process. + * @returns {Function} Returns the function. + */ +function toFunction(value) { + return typeof value == 'function' ? value : identity; +} + +export default toFunction; diff --git a/internal/toIterable.js b/internal/toIterable.js deleted file mode 100644 index dcce3cf9c..000000000 --- a/internal/toIterable.js +++ /dev/null @@ -1,22 +0,0 @@ -import isArrayLike from './isArrayLike'; -import isObject from '../lang/isObject'; -import values from '../object/values'; - -/** - * Converts `value` to an array-like object if it's not one. - * - * @private - * @param {*} value The value to process. - * @returns {Array|Object} Returns the array-like object. - */ -function toIterable(value) { - if (value == null) { - return []; - } - if (!isArrayLike(value)) { - return values(value); - } - return isObject(value) ? value : Object(value); -} - -export default toIterable; diff --git a/internal/toObject.js b/internal/toObject.js deleted file mode 100644 index fa7de0eb9..000000000 --- a/internal/toObject.js +++ /dev/null @@ -1,14 +0,0 @@ -import isObject from '../lang/isObject'; - -/** - * Converts `value` to an object if it's not one. - * - * @private - * @param {*} value The value to process. - * @returns {Object} Returns the object. - */ -function toObject(value) { - return isObject(value) ? value : Object(value); -} - -export default toObject; diff --git a/internal/trimmedLeftIndex.js b/internal/trimmedLeftIndex.js deleted file mode 100644 index bfa0d8d1c..000000000 --- a/internal/trimmedLeftIndex.js +++ /dev/null @@ -1,19 +0,0 @@ -import isSpace from './isSpace'; - -/** - * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the first non-whitespace character. - */ -function trimmedLeftIndex(string) { - var index = -1, - length = string.length; - - while (++index < length && isSpace(string.charCodeAt(index))) {} - return index; -} - -export default trimmedLeftIndex; diff --git a/internal/trimmedRightIndex.js b/internal/trimmedRightIndex.js deleted file mode 100644 index dbaf53932..000000000 --- a/internal/trimmedRightIndex.js +++ /dev/null @@ -1,18 +0,0 @@ -import isSpace from './isSpace'; - -/** - * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ -function trimmedRightIndex(string) { - var index = string.length; - - while (index-- && isSpace(string.charCodeAt(index))) {} - return index; -} - -export default trimmedRightIndex; diff --git a/internal/wrapperClone.js b/internal/wrapperClone.js index 57b88baf2..c9b8f0752 100644 --- a/internal/wrapperClone.js +++ b/internal/wrapperClone.js @@ -1,6 +1,6 @@ import LazyWrapper from './LazyWrapper'; import LodashWrapper from './LodashWrapper'; -import arrayCopy from './arrayCopy'; +import copyArray from './copyArray'; /** * Creates a clone of `wrapper`. @@ -10,9 +10,14 @@ import arrayCopy from './arrayCopy'; * @returns {Object} Returns the cloned wrapper. */ function wrapperClone(wrapper) { - return wrapper instanceof LazyWrapper - ? wrapper.clone() - : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; } export default wrapperClone; diff --git a/intersection.js b/intersection.js new file mode 100644 index 000000000..61b52321f --- /dev/null +++ b/intersection.js @@ -0,0 +1,27 @@ +import arrayMap from './internal/arrayMap'; +import baseIntersection from './internal/baseIntersection'; +import rest from './rest'; +import toArrayLikeObject from './internal/toArrayLikeObject'; + +/** + * Creates an array of unique values that are included in all of the provided + * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of shared values. + * @example + * _.intersection([2, 1], [4, 2], [1, 2]); + * // => [2] + */ +var intersection = rest(function(arrays) { + var mapped = arrayMap(arrays, toArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; +}); + +export default intersection; diff --git a/intersectionBy.js b/intersectionBy.js new file mode 100644 index 000000000..ff8cd2870 --- /dev/null +++ b/intersectionBy.js @@ -0,0 +1,42 @@ +import arrayMap from './internal/arrayMap'; +import baseIntersection from './internal/baseIntersection'; +import baseIteratee from './internal/baseIteratee'; +import last from './last'; +import rest from './rest'; +import toArrayLikeObject from './internal/toArrayLikeObject'; + +/** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of shared values. + * @example + * + * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor); + * // => [2.1] + * + * // using the `_.property` iteratee shorthand + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ +var intersectionBy = rest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, toArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, baseIteratee(iteratee)) + : []; +}); + +export default intersectionBy; diff --git a/intersectionWith.js b/intersectionWith.js new file mode 100644 index 000000000..8a4076246 --- /dev/null +++ b/intersectionWith.js @@ -0,0 +1,40 @@ +import arrayMap from './internal/arrayMap'; +import baseIntersection from './internal/baseIntersection'; +import last from './last'; +import rest from './rest'; +import toArrayLikeObject from './internal/toArrayLikeObject'; + +/** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ +var intersectionWith = rest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, toArrayLikeObject); + + if (comparator === last(mapped)) { + comparator = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; +}); + +export default intersectionWith; diff --git a/object/invert.js b/invert.js similarity index 55% rename from object/invert.js rename to invert.js index 6f1e499ef..9743942c9 100644 --- a/object/invert.js +++ b/invert.js @@ -1,7 +1,7 @@ -import isIterateeCall from '../internal/isIterateeCall'; +import arrayReduce from './internal/arrayReduce'; import keys from './keys'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to check objects for own properties. */ @@ -10,14 +10,14 @@ var hasOwnProperty = objectProto.hasOwnProperty; /** * Creates an object composed of the inverted keys and values of `object`. * If `object` contains duplicate values, subsequent values overwrite property - * assignments of previous values unless `multiValue` is `true`. + * assignments of previous values unless `multiVal` is `true`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to invert. - * @param {boolean} [multiValue] Allow multiple values per key. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param {boolean} [multiVal] Allow multiple values per key. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Object} Returns the new inverted object. * @example * @@ -26,24 +26,14 @@ var hasOwnProperty = objectProto.hasOwnProperty; * _.invert(object); * // => { '1': 'c', '2': 'b' } * - * // with `multiValue` + * // with `multiVal` * _.invert(object, true); * // => { '1': ['a', 'c'], '2': ['b'] } */ -function invert(object, multiValue, guard) { - if (guard && isIterateeCall(object, multiValue, guard)) { - multiValue = undefined; - } - var index = -1, - props = keys(object), - length = props.length, - result = {}; - - while (++index < length) { - var key = props[index], - value = object[key]; - - if (multiValue) { +function invert(object, multiVal, guard) { + return arrayReduce(keys(object), function(result, key) { + var value = object[key]; + if (multiVal && !guard) { if (hasOwnProperty.call(result, value)) { result[value].push(key); } else { @@ -53,8 +43,8 @@ function invert(object, multiValue, guard) { else { result[value] = key; } - } - return result; + return result; + }, {}); } export default invert; diff --git a/invoke.js b/invoke.js new file mode 100644 index 000000000..42d4e76a7 --- /dev/null +++ b/invoke.js @@ -0,0 +1,23 @@ +import baseInvoke from './internal/baseInvoke'; +import rest from './rest'; + +/** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ +var invoke = rest(baseInvoke); + +export default invoke; diff --git a/collection/invoke.js b/invokeMap.js similarity index 59% rename from collection/invoke.js rename to invokeMap.js index 56a5ef126..becc750e2 100644 --- a/collection/invoke.js +++ b/invokeMap.js @@ -1,8 +1,9 @@ -import baseEach from '../internal/baseEach'; -import invokePath from '../internal/invokePath'; -import isArrayLike from '../internal/isArrayLike'; -import isKey from '../internal/isKey'; -import restParam from '../function/restParam'; +import apply from './internal/apply'; +import baseEach from './internal/baseEach'; +import baseInvoke from './internal/baseInvoke'; +import isArrayLike from './isArrayLike'; +import isKey from './internal/isKey'; +import rest from './rest'; /** * Invokes the method at `path` of each element in `collection`, returning @@ -13,20 +14,20 @@ import restParam from '../function/restParam'; * @static * @memberOf _ * @category Collection - * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|string} path The path of the method to invoke or * the function invoked per iteration. - * @param {...*} [args] The arguments to invoke the method with. + * @param {...*} [args] The arguments to invoke each method with. * @returns {Array} Returns the array of results. * @example * - * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * - * _.invoke([123, 456], String.prototype.split, ''); + * _.invokeMap([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ -var invoke = restParam(function(collection, path, args) { +var invokeMap = rest(function(collection, path, args) { var index = -1, isFunc = typeof path == 'function', isProp = isKey(path), @@ -34,9 +35,9 @@ var invoke = restParam(function(collection, path, args) { baseEach(collection, function(value) { var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); - result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args); }); return result; }); -export default invoke; +export default invokeMap; diff --git a/isArguments.js b/isArguments.js new file mode 100644 index 000000000..62c5e3642 --- /dev/null +++ b/isArguments.js @@ -0,0 +1,43 @@ +import isArrayLikeObject from './isArrayLikeObject'; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +export default isArguments; diff --git a/isArray.js b/isArray.js new file mode 100644 index 000000000..8c1d036f2 --- /dev/null +++ b/isArray.js @@ -0,0 +1,26 @@ +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @type Function + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +export default isArray; diff --git a/isArrayLike.js b/isArrayLike.js new file mode 100644 index 000000000..e4614b565 --- /dev/null +++ b/isArrayLike.js @@ -0,0 +1,35 @@ +import getLength from './internal/getLength'; +import isFunction from './isFunction'; +import isLength from './isLength'; + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @type Function + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && + !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value)); +} + +export default isArrayLike; diff --git a/isArrayLikeObject.js b/isArrayLikeObject.js new file mode 100644 index 000000000..c73838a38 --- /dev/null +++ b/isArrayLikeObject.js @@ -0,0 +1,32 @@ +import isArrayLike from './isArrayLike'; +import isObjectLike from './isObjectLike'; + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @type Function + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +export default isArrayLikeObject; diff --git a/lang/isBoolean.js b/isBoolean.js similarity index 72% rename from lang/isBoolean.js rename to isBoolean.js index f6a6f8674..27a0f2222 100644 --- a/lang/isBoolean.js +++ b/isBoolean.js @@ -1,16 +1,16 @@ -import isObjectLike from '../internal/isObjectLike'; +import isObjectLike from './isObjectLike'; /** `Object#toString` result references. */ var boolTag = '[object Boolean]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a boolean primitive or object. @@ -29,7 +29,8 @@ var objToString = objectProto.toString; * // => false */ function isBoolean(value) { - return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag); + return value === true || value === false || + (isObjectLike(value) && objectToString.call(value) == boolTag); } export default isBoolean; diff --git a/lang/isDate.js b/isDate.js similarity index 76% rename from lang/isDate.js rename to isDate.js index 7befa7271..0218fb2b9 100644 --- a/lang/isDate.js +++ b/isDate.js @@ -1,16 +1,16 @@ -import isObjectLike from '../internal/isObjectLike'; +import isObjectLike from './isObjectLike'; /** `Object#toString` result references. */ var dateTag = '[object Date]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a `Date` object. @@ -29,7 +29,7 @@ var objToString = objectProto.toString; * // => false */ function isDate(value) { - return isObjectLike(value) && objToString.call(value) == dateTag; + return isObjectLike(value) && objectToString.call(value) == dateTag; } export default isDate; diff --git a/lang/isElement.js b/isElement.js similarity index 83% rename from lang/isElement.js rename to isElement.js index 5bb92d4f2..14ab21951 100644 --- a/lang/isElement.js +++ b/isElement.js @@ -1,8 +1,8 @@ -import isObjectLike from '../internal/isObjectLike'; +import isObjectLike from './isObjectLike'; import isPlainObject from './isPlainObject'; /** - * Checks if `value` is a DOM element. + * Checks if `value` is likely a DOM element. * * @static * @memberOf _ diff --git a/lang/isEmpty.js b/isEmpty.js similarity index 58% rename from lang/isEmpty.js rename to isEmpty.js index 16737095e..dc5d66203 100644 --- a/lang/isEmpty.js +++ b/isEmpty.js @@ -1,10 +1,7 @@ -import isArguments from './isArguments'; -import isArray from './isArray'; -import isArrayLike from '../internal/isArrayLike'; import isFunction from './isFunction'; -import isObjectLike from '../internal/isObjectLike'; -import isString from './isString'; -import keys from '../object/keys'; +import isObjectLike from './isObjectLike'; +import keys from './keys'; +import size from './size'; /** * Checks if `value` is empty. A value is considered empty unless it's an @@ -34,14 +31,9 @@ import keys from '../object/keys'; * // => false */ function isEmpty(value) { - if (value == null) { - return true; - } - if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || - (isObjectLike(value) && isFunction(value.splice)))) { - return !value.length; - } - return !keys(value).length; + return (!isObjectLike(value) || isFunction(value.splice)) + ? !size(value) + : !keys(value).length; } export default isEmpty; diff --git a/isEqual.js b/isEqual.js new file mode 100644 index 000000000..586548aa1 --- /dev/null +++ b/isEqual.js @@ -0,0 +1,34 @@ +import baseIsEqual from './internal/baseIsEqual'; + +/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are **not** supported. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'user': 'fred' }; + * var other = { 'user': 'fred' }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ +function isEqual(value, other) { + return baseIsEqual(value, other); +} + +export default isEqual; diff --git a/isEqualWith.js b/isEqualWith.js new file mode 100644 index 000000000..f7397398e --- /dev/null +++ b/isEqualWith.js @@ -0,0 +1,40 @@ +import baseIsEqual from './internal/baseIsEqual'; + +/** + * This method is like `_.isEqual` except that it accepts `customizer` which is + * invoked to compare values. If `customizer` returns `undefined` comparisons are + * handled by the method instead. The `customizer` is invoked with up to seven arguments: + * (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ +function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; +} + +export default isEqualWith; diff --git a/lang/isError.js b/isError.js similarity index 74% rename from lang/isError.js rename to isError.js index 9bbece9a1..6ec72aac8 100644 --- a/lang/isError.js +++ b/isError.js @@ -1,16 +1,16 @@ -import isObjectLike from '../internal/isObjectLike'; +import isObjectLike from './isObjectLike'; /** `Object#toString` result references. */ var errorTag = '[object Error]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, @@ -30,7 +30,8 @@ var objToString = objectProto.toString; * // => false */ function isError(value) { - return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag; + return isObjectLike(value) && + typeof value.message == 'string' && objectToString.call(value) == errorTag; } export default isError; diff --git a/lang/isFinite.js b/isFinite.js similarity index 54% rename from lang/isFinite.js rename to isFinite.js index 4e59703c1..057d5db27 100644 --- a/lang/isFinite.js +++ b/isFinite.js @@ -1,12 +1,12 @@ -import root from '../internal/root'; +import root from './internal/root'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeIsFinite = root.isFinite; /** * Checks if `value` is a finite primitive number. * - * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite). + * **Note:** This method is based on [`Number.isFinite`](https://mdn.io/Number/isFinite). * * @static * @memberOf _ @@ -15,17 +15,14 @@ var nativeIsFinite = root.isFinite; * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * - * _.isFinite(10); + * _.isFinite(3); * // => true * - * _.isFinite('10'); - * // => false + * _.isFinite(Number.MAX_VALUE); + * // => true * - * _.isFinite(true); - * // => false - * - * _.isFinite(Object(10)); - * // => false + * _.isFinite(3.14); + * // => true * * _.isFinite(Infinity); * // => false diff --git a/lang/isFunction.js b/isFunction.js similarity index 63% rename from lang/isFunction.js rename to isFunction.js index 32c5fda19..5e2e6b609 100644 --- a/lang/isFunction.js +++ b/isFunction.js @@ -1,16 +1,17 @@ import isObject from './isObject'; /** `Object#toString` result references. */ -var funcTag = '[object Function]'; +var funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a `Function` object. @@ -30,9 +31,10 @@ var objToString = objectProto.toString; */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in older versions of Chrome and Safari which return 'function' for regexes - // and Safari 8 which returns 'object' for typed array constructors. - return isObject(value) && objToString.call(value) == funcTag; + // in Safari 8 which returns 'object' for typed array constructors, and + // PhantomJS 1.9 which returns 'function' for `NodeList` instances. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; } export default isFunction; diff --git a/isInteger.js b/isInteger.js new file mode 100644 index 000000000..4c8799b73 --- /dev/null +++ b/isInteger.js @@ -0,0 +1,31 @@ +import toInteger from './toInteger'; + +/** + * Checks if `value` is an integer. + * + * **Note:** This method is based on [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ +function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); +} + +export default isInteger; diff --git a/isLength.js b/isLength.js new file mode 100644 index 000000000..d13d42318 --- /dev/null +++ b/isLength.js @@ -0,0 +1,32 @@ +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +export default isLength; diff --git a/isMatch.js b/isMatch.js new file mode 100644 index 000000000..e32ffec0c --- /dev/null +++ b/isMatch.js @@ -0,0 +1,30 @@ +import baseIsMatch from './internal/baseIsMatch'; +import getMatchData from './internal/getMatchData'; + +/** + * Performs a deep comparison between `object` and `source` to determine if + * `object` contains equivalent property values. + * + * **Note:** This method supports comparing the same values as `_.isEqual`. + * + * @static + * @memberOf _ + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'user': 'fred', 'age': 40 }; + * + * _.isMatch(object, { 'age': 40 }); + * // => true + * + * _.isMatch(object, { 'age': 36 }); + * // => false + */ +function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); +} + +export default isMatch; diff --git a/isMatchWith.js b/isMatchWith.js new file mode 100644 index 000000000..97539690d --- /dev/null +++ b/isMatchWith.js @@ -0,0 +1,40 @@ +import baseIsMatch from './internal/baseIsMatch'; +import getMatchData from './internal/getMatchData'; + +/** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined` comparisons + * are handled by the method instead. The `customizer` is invoked with three + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ +function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); +} + +export default isMatchWith; diff --git a/lang/isNaN.js b/isNaN.js similarity index 96% rename from lang/isNaN.js rename to isNaN.js index d2b2d0f5a..099a9970c 100644 --- a/lang/isNaN.js +++ b/isNaN.js @@ -27,7 +27,7 @@ import isNumber from './isNumber'; */ function isNaN(value) { // An `NaN` primitive is the only value that is not equal to itself. - // Perform the `toStringTag` check first to avoid errors with some host objects in IE. + // Perform the `toStringTag` check first to avoid errors with some ActiveX objects in IE. return isNumber(value) && value != +value; } diff --git a/lang/isNative.js b/isNative.js similarity index 63% rename from lang/isNative.js rename to isNative.js index e037e95ee..18bf0432e 100644 --- a/lang/isNative.js +++ b/isNative.js @@ -1,21 +1,25 @@ import isFunction from './isFunction'; -import isObjectLike from '../internal/isObjectLike'; +import isHostObject from './internal/isHostObject'; +import isObjectLike from './isObjectLike'; + +/** Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; /** Used to detect host constructors (Safari > 5). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to resolve the decompiled source of functions. */ -var fnToString = Function.prototype.toString; +var funcToString = Function.prototype.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + - fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); @@ -40,9 +44,10 @@ function isNative(value) { return false; } if (isFunction(value)) { - return reIsNative.test(fnToString.call(value)); + return reIsNative.test(funcToString.call(value)); } - return isObjectLike(value) && reIsHostCtor.test(value); + return isObjectLike(value) && + (isHostObject(value) ? reIsNative : reIsHostCtor).test(value); } export default isNative; diff --git a/isNil.js b/isNil.js new file mode 100644 index 000000000..44603d47f --- /dev/null +++ b/isNil.js @@ -0,0 +1,24 @@ +/** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ +function isNil(value) { + return value == null; +} + +export default isNil; diff --git a/lang/isNull.js b/isNull.js similarity index 100% rename from lang/isNull.js rename to isNull.js diff --git a/lang/isNumber.js b/isNumber.js similarity index 68% rename from lang/isNumber.js rename to isNumber.js index dcc8c3db8..0fcfce16b 100644 --- a/lang/isNumber.js +++ b/isNumber.js @@ -1,16 +1,16 @@ -import isObjectLike from '../internal/isObjectLike'; +import isObjectLike from './isObjectLike'; /** `Object#toString` result references. */ var numberTag = '[object Number]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a `Number` primitive or object. @@ -25,17 +25,21 @@ var objToString = objectProto.toString; * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.isNumber(8.4); + * _.isNumber(3); * // => true * - * _.isNumber(NaN); + * _.isNumber(Number.MIN_VALUE); * // => true * - * _.isNumber('8.4'); + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); * // => false */ function isNumber(value) { - return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag); + return typeof value == 'number' || + (isObjectLike(value) && objectToString.call(value) == numberTag); } export default isNumber; diff --git a/lang/isObject.js b/isObject.js similarity index 92% rename from lang/isObject.js rename to isObject.js index 19bba5e4a..8aebc4b8d 100644 --- a/lang/isObject.js +++ b/isObject.js @@ -15,7 +15,10 @@ * _.isObject([1, 2, 3]); * // => true * - * _.isObject(1); + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); * // => false */ function isObject(value) { diff --git a/isObjectLike.js b/isObjectLike.js new file mode 100644 index 000000000..4d1211a9a --- /dev/null +++ b/isObjectLike.js @@ -0,0 +1,28 @@ +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +export default isObjectLike; diff --git a/isPlainObject.js b/isPlainObject.js new file mode 100644 index 000000000..dcef5ebc6 --- /dev/null +++ b/isPlainObject.js @@ -0,0 +1,68 @@ +import isHostObject from './internal/isHostObject'; +import isObjectLike from './isObjectLike'; + +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = Function.prototype.toString; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString.call(Object); + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var getPrototypeOf = Object.getPrototypeOf; + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!isObjectLike(value) || objectToString.call(value) != objectTag || isHostObject(value)) { + return false; + } + var proto = objectProto; + if (typeof value.constructor == 'function') { + proto = getPrototypeOf(value); + } + if (proto === null) { + return true; + } + var Ctor = proto.constructor; + return (typeof Ctor == 'function' && + Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); +} + +export default isPlainObject; diff --git a/lang/isRegExp.js b/isRegExp.js similarity index 81% rename from lang/isRegExp.js rename to isRegExp.js index 6bc150988..ce968c52c 100644 --- a/lang/isRegExp.js +++ b/isRegExp.js @@ -3,14 +3,14 @@ import isObject from './isObject'; /** `Object#toString` result references. */ var regexpTag = '[object RegExp]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a `RegExp` object. @@ -29,7 +29,7 @@ var objToString = objectProto.toString; * // => false */ function isRegExp(value) { - return isObject(value) && objToString.call(value) == regexpTag; + return isObject(value) && objectToString.call(value) == regexpTag; } export default isRegExp; diff --git a/isSafeInteger.js b/isSafeInteger.js new file mode 100644 index 000000000..c81338df9 --- /dev/null +++ b/isSafeInteger.js @@ -0,0 +1,35 @@ +import isInteger from './isInteger'; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ +function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; +} + +export default isSafeInteger; diff --git a/lang/isString.js b/isString.js similarity index 69% rename from lang/isString.js rename to isString.js index f596442d5..7dd6d3554 100644 --- a/lang/isString.js +++ b/isString.js @@ -1,16 +1,17 @@ -import isObjectLike from '../internal/isObjectLike'; +import isArray from './isArray'; +import isObjectLike from './isObjectLike'; /** `Object#toString` result references. */ var stringTag = '[object String]'; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a `String` primitive or object. @@ -29,7 +30,8 @@ var objToString = objectProto.toString; * // => false */ function isString(value) { - return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag); + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); } export default isString; diff --git a/isSymbol.js b/isSymbol.js new file mode 100644 index 000000000..37ed8d98b --- /dev/null +++ b/isSymbol.js @@ -0,0 +1,36 @@ +import isObjectLike from './isObjectLike'; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +export default isSymbol; diff --git a/lang/isTypedArray.js b/isTypedArray.js similarity index 91% rename from lang/isTypedArray.js rename to isTypedArray.js index a8b1c9135..e1f9e5481 100644 --- a/lang/isTypedArray.js +++ b/isTypedArray.js @@ -1,5 +1,5 @@ -import isLength from '../internal/isLength'; -import isObjectLike from '../internal/isObjectLike'; +import isLength from './isLength'; +import isObjectLike from './isObjectLike'; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', @@ -42,14 +42,14 @@ typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; -/** Used for native method references. */ +/** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ -var objToString = objectProto.toString; +var objectToString = objectProto.toString; /** * Checks if `value` is classified as a typed array. @@ -68,7 +68,7 @@ var objToString = objectProto.toString; * // => false */ function isTypedArray(value) { - return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; } export default isTypedArray; diff --git a/lang/isUndefined.js b/isUndefined.js similarity index 100% rename from lang/isUndefined.js rename to isUndefined.js diff --git a/iteratee.js b/iteratee.js new file mode 100644 index 000000000..7e6a5ba2a --- /dev/null +++ b/iteratee.js @@ -0,0 +1,41 @@ +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; +import isObjectLike from './isObjectLike'; +import matches from './matches'; + +/** + * Creates a function that invokes `func` with the arguments of the created + * function. If `func` is a property name the created callback returns the + * property value for a given element. If `func` is an object the created + * callback returns `true` for elements that contain the equivalent object properties, otherwise it returns `false`. + * + * @static + * @memberOf _ + * @category Util + * @param {*} [func=_.identity] The value to convert to a callback. + * @returns {Function} Returns the callback. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // create custom iteratee shorthands + * _.iteratee = _.wrap(_.iteratee, function(callback, func) { + * var p = /^(\S+)\s*([<>])\s*(\S+)$/.exec(func); + * return !p ? callback(func) : function(object) { + * return (p[2] == '>' ? object[p[1]] > p[3] : object[p[1]] < p[3]); + * }; + * }); + * + * _.filter(users, 'age > 36'); + * // => [{ 'user': 'fred', 'age': 40 }] + */ +function iteratee(func) { + return (isObjectLike(func) && !isArray(func)) + ? matches(func) + : baseIteratee(func); +} + +export default iteratee; diff --git a/join.js b/join.js new file mode 100644 index 000000000..ad2b69c15 --- /dev/null +++ b/join.js @@ -0,0 +1,25 @@ +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeJoin = arrayProto.join; + +/** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ +function join(array, separator) { + return array ? nativeJoin.call(array, separator) : ''; +} + +export default join; diff --git a/string/kebabCase.js b/kebabCase.js similarity index 90% rename from string/kebabCase.js rename to kebabCase.js index 51ee6b29e..3af75437e 100644 --- a/string/kebabCase.js +++ b/kebabCase.js @@ -1,4 +1,4 @@ -import createCompounder from '../internal/createCompounder'; +import createCompounder from './internal/createCompounder'; /** * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). diff --git a/keyBy.js b/keyBy.js new file mode 100644 index 000000000..c7b18da46 --- /dev/null +++ b/keyBy.js @@ -0,0 +1,34 @@ +import createAggregator from './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 is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var keyData = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(keyData, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(keyData, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + */ +var keyBy = createAggregator(function(result, value, key) { + result[key] = value; +}); + +export default keyBy; diff --git a/keys.js b/keys.js new file mode 100644 index 000000000..71dd5436d --- /dev/null +++ b/keys.js @@ -0,0 +1,55 @@ +import baseHas from './internal/baseHas'; +import baseKeys from './internal/baseKeys'; +import indexKeys from './internal/indexKeys'; +import isArrayLike from './isArrayLike'; +import isIndex from './internal/isIndex'; +import isPrototype from './internal/isPrototype'; + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * for more details. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +function keys(object) { + var isProto = isPrototype(object); + if (!(isProto || isArrayLike(object))) { + return baseKeys(object); + } + var indexes = indexKeys(object), + skipIndexes = !!indexes, + result = indexes || [], + length = result.length; + + for (var key in object) { + if (baseHas(object, key) && + !(skipIndexes && (key == 'length' || isIndex(key, length))) && + !(isProto && key == 'constructor')) { + result.push(key); + } + } + return result; +} + +export default keys; diff --git a/keysIn.js b/keysIn.js new file mode 100644 index 000000000..d3e06e263 --- /dev/null +++ b/keysIn.js @@ -0,0 +1,54 @@ +import baseKeysIn from './internal/baseKeysIn'; +import indexKeys from './internal/indexKeys'; +import isIndex from './internal/isIndex'; +import isPrototype from './internal/isPrototype'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + var index = -1, + isProto = isPrototype(object), + props = baseKeysIn(object), + propsLength = props.length, + indexes = indexKeys(object), + skipIndexes = !!indexes, + result = indexes || [], + length = result.length; + + while (++index < propsLength) { + var key = props[index]; + if (!(skipIndexes && (key == 'length' || isIndex(key, length))) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +export default keysIn; diff --git a/lang.default.js b/lang.default.js new file mode 100644 index 000000000..b72c6c85b --- /dev/null +++ b/lang.default.js @@ -0,0 +1,60 @@ +import clone from './clone'; +import cloneDeep from './cloneDeep'; +import cloneDeepWith from './cloneDeepWith'; +import cloneWith from './cloneWith'; +import eq from './eq'; +import gt from './gt'; +import gte from './gte'; +import isArguments from './isArguments'; +import isArray from './isArray'; +import isArrayLike from './isArrayLike'; +import isArrayLikeObject from './isArrayLikeObject'; +import isBoolean from './isBoolean'; +import isDate from './isDate'; +import isElement from './isElement'; +import isEmpty from './isEmpty'; +import isEqual from './isEqual'; +import isEqualWith from './isEqualWith'; +import isError from './isError'; +import isFinite from './isFinite'; +import isFunction from './isFunction'; +import isInteger from './isInteger'; +import isLength from './isLength'; +import isMatch from './isMatch'; +import isMatchWith from './isMatchWith'; +import isNaN from './isNaN'; +import isNative from './isNative'; +import isNil from './isNil'; +import isNull from './isNull'; +import isNumber from './isNumber'; +import isObject from './isObject'; +import isObjectLike from './isObjectLike'; +import isPlainObject from './isPlainObject'; +import isRegExp from './isRegExp'; +import isSafeInteger from './isSafeInteger'; +import isString from './isString'; +import isSymbol from './isSymbol'; +import isTypedArray from './isTypedArray'; +import isUndefined from './isUndefined'; +import lt from './lt'; +import lte from './lte'; +import toArray from './toArray'; +import toInteger from './toInteger'; +import toLength from './toLength'; +import toNumber from './toNumber'; +import toPlainObject from './toPlainObject'; +import toSafeInteger from './toSafeInteger'; +import toString from './toString'; + +export default { + clone, cloneDeep, cloneDeepWith, cloneWith, eq, + gt, gte, isArguments, isArray, isArrayLike, + isArrayLikeObject, isBoolean, isDate, isElement, isEmpty, + isEqual, isEqualWith, isError, isFinite, isFunction, + isInteger, isLength, isMatch, isMatchWith, isNaN, + isNative, isNil, isNull, isNumber, isObject, + isObjectLike, isPlainObject, isRegExp, isSafeInteger, isString, + isSymbol, isTypedArray, isUndefined, lt, lte, + toArray, toInteger, toLength, toNumber, toPlainObject, + toSafeInteger, toString +}; diff --git a/lang.js b/lang.js index 3d281a2c0..5295b18d0 100644 --- a/lang.js +++ b/lang.js @@ -1,63 +1,48 @@ -import clone from './lang/clone'; -import cloneDeep from './lang/cloneDeep'; -import eq from './lang/eq'; -import gt from './lang/gt'; -import gte from './lang/gte'; -import isArguments from './lang/isArguments'; -import isArray from './lang/isArray'; -import isBoolean from './lang/isBoolean'; -import isDate from './lang/isDate'; -import isElement from './lang/isElement'; -import isEmpty from './lang/isEmpty'; -import isEqual from './lang/isEqual'; -import isError from './lang/isError'; -import isFinite from './lang/isFinite'; -import isFunction from './lang/isFunction'; -import isMatch from './lang/isMatch'; -import isNaN from './lang/isNaN'; -import isNative from './lang/isNative'; -import isNull from './lang/isNull'; -import isNumber from './lang/isNumber'; -import isObject from './lang/isObject'; -import isPlainObject from './lang/isPlainObject'; -import isRegExp from './lang/isRegExp'; -import isString from './lang/isString'; -import isTypedArray from './lang/isTypedArray'; -import isUndefined from './lang/isUndefined'; -import lt from './lang/lt'; -import lte from './lang/lte'; -import toArray from './lang/toArray'; -import toPlainObject from './lang/toPlainObject'; - -export default { - 'clone': clone, - 'cloneDeep': cloneDeep, - 'eq': eq, - 'gt': gt, - 'gte': gte, - 'isArguments': isArguments, - 'isArray': isArray, - 'isBoolean': isBoolean, - 'isDate': isDate, - 'isElement': isElement, - 'isEmpty': isEmpty, - 'isEqual': isEqual, - 'isError': isError, - 'isFinite': isFinite, - 'isFunction': isFunction, - 'isMatch': isMatch, - 'isNaN': isNaN, - 'isNative': isNative, - 'isNull': isNull, - 'isNumber': isNumber, - 'isObject': isObject, - 'isPlainObject': isPlainObject, - 'isRegExp': isRegExp, - 'isString': isString, - 'isTypedArray': isTypedArray, - 'isUndefined': isUndefined, - 'lt': lt, - 'lte': lte, - 'toArray': toArray, - 'toPlainObject': toPlainObject -}; +export { default as clone } from './clone'; +export { default as cloneDeep } from './cloneDeep'; +export { default as cloneDeepWith } from './cloneDeepWith'; +export { default as cloneWith } from './cloneWith'; +export { default as eq } from './eq'; +export { default as gt } from './gt'; +export { default as gte } from './gte'; +export { default as isArguments } from './isArguments'; +export { default as isArray } from './isArray'; +export { default as isArrayLike } from './isArrayLike'; +export { default as isArrayLikeObject } from './isArrayLikeObject'; +export { default as isBoolean } from './isBoolean'; +export { default as isDate } from './isDate'; +export { default as isElement } from './isElement'; +export { default as isEmpty } from './isEmpty'; +export { default as isEqual } from './isEqual'; +export { default as isEqualWith } from './isEqualWith'; +export { default as isError } from './isError'; +export { default as isFinite } from './isFinite'; +export { default as isFunction } from './isFunction'; +export { default as isInteger } from './isInteger'; +export { default as isLength } from './isLength'; +export { default as isMatch } from './isMatch'; +export { default as isMatchWith } from './isMatchWith'; +export { default as isNaN } from './isNaN'; +export { default as isNative } from './isNative'; +export { default as isNil } from './isNil'; +export { default as isNull } from './isNull'; +export { default as isNumber } from './isNumber'; +export { default as isObject } from './isObject'; +export { default as isObjectLike } from './isObjectLike'; +export { default as isPlainObject } from './isPlainObject'; +export { default as isRegExp } from './isRegExp'; +export { default as isSafeInteger } from './isSafeInteger'; +export { default as isString } from './isString'; +export { default as isSymbol } from './isSymbol'; +export { default as isTypedArray } from './isTypedArray'; +export { default as isUndefined } from './isUndefined'; +export { default as lt } from './lt'; +export { default as lte } from './lte'; +export { default as toArray } from './toArray'; +export { default as toInteger } from './toInteger'; +export { default as toLength } from './toLength'; +export { default as toNumber } from './toNumber'; +export { default as toPlainObject } from './toPlainObject'; +export { default as toSafeInteger } from './toSafeInteger'; +export { default as toString } from './toString'; +export { default as default } from './lang.default'; diff --git a/lang/clone.js b/lang/clone.js deleted file mode 100644 index a277bca43..000000000 --- a/lang/clone.js +++ /dev/null @@ -1,70 +0,0 @@ -import baseClone from '../internal/baseClone'; -import bindCallback from '../internal/bindCallback'; -import isIterateeCall from '../internal/isIterateeCall'; - -/** - * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, - * otherwise they are assigned by reference. If `customizer` is provided it's - * invoked to produce the cloned values. If `customizer` returns `undefined` - * cloning is handled by the method instead. The `customizer` is bound to - * `thisArg` and invoked with up to three argument; (value [, index|key, object]). - * - * **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. - * - * @static - * @memberOf _ - * @category Lang - * @param {*} value The value to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @param {Function} [customizer] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {*} Returns the cloned value. - * @example - * - * var users = [ - * { 'user': 'barney' }, - * { 'user': 'fred' } - * ]; - * - * var shallow = _.clone(users); - * shallow[0] === users[0]; - * // => true - * - * var deep = _.clone(users, true); - * deep[0] === users[0]; - * // => false - * - * // using a customizer callback - * var el = _.clone(document.body, function(value) { - * if (_.isElement(value)) { - * return value.cloneNode(false); - * } - * }); - * - * el === document.body - * // => false - * el.nodeName - * // => BODY - * el.childNodes.length; - * // => 0 - */ -function clone(value, isDeep, customizer, thisArg) { - if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) { - isDeep = false; - } - else if (typeof isDeep == 'function') { - thisArg = customizer; - customizer = isDeep; - isDeep = false; - } - return typeof customizer == 'function' - ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) - : baseClone(value, isDeep); -} - -export default clone; diff --git a/lang/cloneDeep.js b/lang/cloneDeep.js deleted file mode 100644 index 2961a5209..000000000 --- a/lang/cloneDeep.js +++ /dev/null @@ -1,55 +0,0 @@ -import baseClone from '../internal/baseClone'; -import bindCallback from '../internal/bindCallback'; - -/** - * Creates a deep clone of `value`. If `customizer` is provided it's invoked - * to produce the cloned values. If `customizer` returns `undefined` cloning - * is handled by the method instead. The `customizer` is bound to `thisArg` - * and invoked with up to three argument; (value [, index|key, object]). - * - * **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. - * - * @static - * @memberOf _ - * @category Lang - * @param {*} value The value to deep clone. - * @param {Function} [customizer] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {*} Returns the deep cloned value. - * @example - * - * var users = [ - * { 'user': 'barney' }, - * { 'user': 'fred' } - * ]; - * - * var deep = _.cloneDeep(users); - * deep[0] === users[0]; - * // => false - * - * // using a customizer callback - * var el = _.cloneDeep(document.body, function(value) { - * if (_.isElement(value)) { - * return value.cloneNode(true); - * } - * }); - * - * el === document.body - * // => false - * el.nodeName - * // => BODY - * el.childNodes.length; - * // => 20 - */ -function cloneDeep(value, customizer, thisArg) { - return typeof customizer == 'function' - ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) - : baseClone(value, true); -} - -export default cloneDeep; diff --git a/lang/eq.js b/lang/eq.js deleted file mode 100644 index fc0698220..000000000 --- a/lang/eq.js +++ /dev/null @@ -1,2 +0,0 @@ -import isEqual from './isEqual' -export default isEqual; diff --git a/lang/isArguments.js b/lang/isArguments.js deleted file mode 100644 index 22140d86c..000000000 --- a/lang/isArguments.js +++ /dev/null @@ -1,34 +0,0 @@ -import isArrayLike from '../internal/isArrayLike'; -import isObjectLike from '../internal/isObjectLike'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** Native method references. */ -var propertyIsEnumerable = objectProto.propertyIsEnumerable; - -/** - * Checks if `value` is classified as an `arguments` object. - * - * @static - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. - * @example - * - * _.isArguments(function() { return arguments; }()); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ -function isArguments(value) { - return isObjectLike(value) && isArrayLike(value) && - hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); -} - -export default isArguments; diff --git a/lang/isArray.js b/lang/isArray.js deleted file mode 100644 index 9af0bf7bc..000000000 --- a/lang/isArray.js +++ /dev/null @@ -1,40 +0,0 @@ -import getNative from '../internal/getNative'; -import isLength from '../internal/isLength'; -import isObjectLike from '../internal/isObjectLike'; - -/** `Object#toString` result references. */ -var arrayTag = '[object Array]'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ -var objToString = objectProto.toString; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeIsArray = getNative(Array, 'isArray'); - -/** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(function() { return arguments; }()); - * // => false - */ -var isArray = nativeIsArray || function(value) { - return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; -}; - -export default isArray; diff --git a/lang/isEqual.js b/lang/isEqual.js deleted file mode 100644 index 50fc64a46..000000000 --- a/lang/isEqual.js +++ /dev/null @@ -1,54 +0,0 @@ -import baseIsEqual from '../internal/baseIsEqual'; -import bindCallback from '../internal/bindCallback'; - -/** - * Performs a deep comparison between two values to determine if they are - * equivalent. If `customizer` is provided it's invoked to compare values. - * If `customizer` returns `undefined` comparisons are handled by the method - * instead. The `customizer` is bound to `thisArg` and invoked with up to - * three arguments: (value, other [, index|key]). - * - * **Note:** This method supports comparing arrays, booleans, `Date` objects, - * numbers, `Object` objects, regexes, and strings. Objects are compared by - * their own, not inherited, enumerable properties. Functions and DOM nodes - * are **not** supported. Provide a customizer function to extend support - * for comparing other values. - * - * @static - * @memberOf _ - * @alias eq - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @param {Function} [customizer] The function to customize value comparisons. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'user': 'fred' }; - * var other = { 'user': 'fred' }; - * - * object == other; - * // => false - * - * _.isEqual(object, other); - * // => true - * - * // using a customizer callback - * var array = ['hello', 'goodbye']; - * var other = ['hi', 'goodbye']; - * - * _.isEqual(array, other, function(value, other) { - * if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) { - * return true; - * } - * }); - * // => true - */ -function isEqual(value, other, customizer, thisArg) { - customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; - var result = customizer ? customizer(value, other) : undefined; - return result === undefined ? baseIsEqual(value, other, customizer) : !!result; -} - -export default isEqual; diff --git a/lang/isMatch.js b/lang/isMatch.js deleted file mode 100644 index e58ef5606..000000000 --- a/lang/isMatch.js +++ /dev/null @@ -1,49 +0,0 @@ -import baseIsMatch from '../internal/baseIsMatch'; -import bindCallback from '../internal/bindCallback'; -import getMatchData from '../internal/getMatchData'; - -/** - * Performs a deep comparison between `object` and `source` to determine if - * `object` contains equivalent property values. If `customizer` is provided - * it's 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). - * - * **Note:** This method supports comparing properties of arrays, booleans, - * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions - * and DOM nodes are **not** supported. Provide a customizer function to extend - * support for comparing other values. - * - * @static - * @memberOf _ - * @category Lang - * @param {Object} object The object to inspect. - * @param {Object} source The object of property values to match. - * @param {Function} [customizer] The function to customize value comparisons. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {boolean} Returns `true` if `object` is a match, else `false`. - * @example - * - * var object = { 'user': 'fred', 'age': 40 }; - * - * _.isMatch(object, { 'age': 40 }); - * // => true - * - * _.isMatch(object, { 'age': 36 }); - * // => false - * - * // using a customizer callback - * var object = { 'greeting': 'hello' }; - * var source = { 'greeting': 'hi' }; - * - * _.isMatch(object, source, function(value, other) { - * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined; - * }); - * // => true - */ -function isMatch(object, source, customizer, thisArg) { - customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; - return baseIsMatch(object, getMatchData(source), customizer); -} - -export default isMatch; diff --git a/lang/isPlainObject.js b/lang/isPlainObject.js deleted file mode 100644 index 8d1724cff..000000000 --- a/lang/isPlainObject.js +++ /dev/null @@ -1,71 +0,0 @@ -import baseForIn from '../internal/baseForIn'; -import isArguments from './isArguments'; -import isObjectLike from '../internal/isObjectLike'; - -/** `Object#toString` result references. */ -var objectTag = '[object Object]'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ -var objToString = objectProto.toString; - -/** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. - * - * **Note:** This method assumes objects created by the `Object` constructor - * have no inherited enumerable properties. - * - * @static - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * _.isPlainObject(new Foo); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true - * - * _.isPlainObject(Object.create(null)); - * // => true - */ -function isPlainObject(value) { - var Ctor; - - // Exit early for non `Object` objects. - if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || - (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { - return false; - } - // IE < 9 iterates inherited properties before own properties. If the first - // iterated property is an object's own property then there are no inherited - // enumerable properties. - var result; - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - baseForIn(value, function(subValue, key) { - result = key; - }); - return result === undefined || hasOwnProperty.call(value, result); -} - -export default isPlainObject; diff --git a/lang/toArray.js b/lang/toArray.js deleted file mode 100644 index bab36a8ad..000000000 --- a/lang/toArray.js +++ /dev/null @@ -1,32 +0,0 @@ -import arrayCopy from '../internal/arrayCopy'; -import getLength from '../internal/getLength'; -import isLength from '../internal/isLength'; -import values from '../object/values'; - -/** - * Converts `value` to an array. - * - * @static - * @memberOf _ - * @category Lang - * @param {*} value The value to convert. - * @returns {Array} Returns the converted array. - * @example - * - * (function() { - * return _.toArray(arguments).slice(1); - * }(1, 2, 3)); - * // => [2, 3] - */ -function toArray(value) { - var length = value ? getLength(value) : 0; - if (!isLength(length)) { - return values(value); - } - if (!length) { - return []; - } - return arrayCopy(value); -} - -export default toArray; diff --git a/array/last.js b/last.js similarity index 100% rename from array/last.js rename to last.js diff --git a/array/lastIndexOf.js b/lastIndexOf.js similarity index 52% rename from array/lastIndexOf.js rename to lastIndexOf.js index f7b1c4cd7..eb56fbc58 100644 --- a/array/lastIndexOf.js +++ b/lastIndexOf.js @@ -1,7 +1,7 @@ -import binaryIndex from '../internal/binaryIndex'; -import indexOfNaN from '../internal/indexOfNaN'; +import indexOfNaN from './internal/indexOfNaN'; +import toInteger from './toInteger'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max, nativeMin = Math.min; @@ -14,8 +14,7 @@ var nativeMax = Math.max, * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. - * @param {boolean|number} [fromIndex=array.length-1] The index to search from - * or `true` to perform a binary search on a sorted array. + * @param {number} [fromIndex=array.length-1] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. * @example * @@ -25,10 +24,6 @@ var nativeMax = Math.max, * // using `fromIndex` * _.lastIndexOf([1, 2, 1, 2], 2, 2); * // => 1 - * - * // performing a binary search - * _.lastIndexOf([1, 1, 2, 2], 2, true); - * // => 3 */ function lastIndexOf(array, value, fromIndex) { var length = array ? array.length : 0; @@ -36,15 +31,9 @@ function lastIndexOf(array, value, fromIndex) { return -1; } var index = length; - if (typeof fromIndex == 'number') { - index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; - } else if (fromIndex) { - index = binaryIndex(array, value, true) - 1; - var other = array[index]; - if (value === value ? (value === other) : (other !== other)) { - return index; - } - return -1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = (index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1)) + 1; } if (value !== value) { return indexOfNaN(array, index, true); diff --git a/lodash.default.js b/lodash.default.js new file mode 100644 index 000000000..819c47bf1 --- /dev/null +++ b/lodash.default.js @@ -0,0 +1,604 @@ +/** + * @license + * lodash 4.0.0 (Custom Build) + * Build: `lodash modularize exports="es" -o ./` + * Copyright 2012-2016 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ +import array from './array'; +import collection from './collection'; +import date from './date'; +import func from './function'; +import lang from './lang'; +import math from './math'; +import number from './number'; +import object from './object'; +import seq from './seq'; +import string from './string'; +import util from './util'; +import LazyWrapper from './internal/LazyWrapper'; +import LodashWrapper from './internal/LodashWrapper'; +import _Symbol from './internal/_Symbol'; +import arrayEach from './internal/arrayEach'; +import arrayPush from './internal/arrayPush'; +import baseForOwn from './internal/baseForOwn'; +import baseFunctions from './internal/baseFunctions'; +import baseInvoke from './internal/baseInvoke'; +import baseIteratee from './internal/baseIteratee'; +import createHybridWrapper from './internal/createHybridWrapper'; +import identity from './identity'; +import isArray from './isArray'; +import isObject from './isObject'; +import keys from './keys'; +import last from './last'; +import lazyClone from './internal/lazyClone'; +import lazyReverse from './internal/lazyReverse'; +import lazyValue from './internal/lazyValue'; +import _mixin from './mixin'; +import realNames from './internal/realNames'; +import rest from './rest'; +import thru from './thru'; +import toInteger from './toInteger'; +import lodash from './wrapperLodash'; + +/** Used as the semantic version number. */ +var VERSION = '4.0.0'; + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_KEY_FLAG = 2; + +/** Used to indicate the type of lazy iteratees. */ +var LAZY_FILTER_FLAG = 1, + LAZY_WHILE_FLAG = 3; + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295; + +/** Used for built-in method references. */ +var arrayProto = Array.prototype, + objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var iteratorSymbol = typeof (iteratorSymbol = _Symbol && _Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +// wrap `_.mixin` so it works when provided only one argument +var mixin = (function(func) { + return function(object, source, options) { + if (options == null) { + var isObj = isObject(source), + props = isObj && keys(source), + methodNames = props && props.length && baseFunctions(source, props); + + if (!(methodNames ? methodNames.length : isObj)) { + options = source; + source = object; + object = this; + } + } + return func(object, source, options); + }; +}(_mixin)); + +// Add functions that return wrapped values when chaining. +lodash.after = func.after; +lodash.ary = func.ary; +lodash.assign = object.assign; +lodash.assignIn = object.assignIn; +lodash.assignInWith = object.assignInWith; +lodash.assignWith = object.assignWith; +lodash.at = collection.at; +lodash.before = func.before; +lodash.bind = func.bind; +lodash.bindAll = util.bindAll; +lodash.bindKey = func.bindKey; +lodash.chain = seq.chain; +lodash.chunk = array.chunk; +lodash.compact = array.compact; +lodash.concat = array.concat; +lodash.cond = util.cond; +lodash.conforms = util.conforms; +lodash.constant = util.constant; +lodash.countBy = collection.countBy; +lodash.create = object.create; +lodash.curry = func.curry; +lodash.curryRight = func.curryRight; +lodash.debounce = func.debounce; +lodash.defaults = object.defaults; +lodash.defaultsDeep = object.defaultsDeep; +lodash.defer = func.defer; +lodash.delay = func.delay; +lodash.difference = array.difference; +lodash.differenceBy = array.differenceBy; +lodash.differenceWith = array.differenceWith; +lodash.drop = array.drop; +lodash.dropRight = array.dropRight; +lodash.dropRightWhile = array.dropRightWhile; +lodash.dropWhile = array.dropWhile; +lodash.fill = array.fill; +lodash.filter = collection.filter; +lodash.flatMap = array.flatMap; +lodash.flatten = array.flatten; +lodash.flattenDeep = array.flattenDeep; +lodash.flip = func.flip; +lodash.flow = util.flow; +lodash.flowRight = util.flowRight; +lodash.fromPairs = array.fromPairs; +lodash.functions = object.functions; +lodash.functionsIn = object.functionsIn; +lodash.groupBy = collection.groupBy; +lodash.initial = array.initial; +lodash.intersection = array.intersection; +lodash.intersectionBy = array.intersectionBy; +lodash.intersectionWith = array.intersectionWith; +lodash.invert = object.invert; +lodash.invokeMap = collection.invokeMap; +lodash.iteratee = util.iteratee; +lodash.keyBy = collection.keyBy; +lodash.keys = keys; +lodash.keysIn = object.keysIn; +lodash.map = collection.map; +lodash.mapKeys = object.mapKeys; +lodash.mapValues = object.mapValues; +lodash.matches = util.matches; +lodash.matchesProperty = util.matchesProperty; +lodash.memoize = func.memoize; +lodash.merge = object.merge; +lodash.mergeWith = object.mergeWith; +lodash.method = util.method; +lodash.methodOf = util.methodOf; +lodash.mixin = mixin; +lodash.negate = func.negate; +lodash.nthArg = util.nthArg; +lodash.omit = object.omit; +lodash.omitBy = object.omitBy; +lodash.once = func.once; +lodash.orderBy = collection.orderBy; +lodash.over = util.over; +lodash.overArgs = func.overArgs; +lodash.overEvery = util.overEvery; +lodash.overSome = util.overSome; +lodash.partial = func.partial; +lodash.partialRight = func.partialRight; +lodash.partition = collection.partition; +lodash.pick = object.pick; +lodash.pickBy = object.pickBy; +lodash.property = util.property; +lodash.propertyOf = util.propertyOf; +lodash.pull = array.pull; +lodash.pullAll = array.pullAll; +lodash.pullAllBy = array.pullAllBy; +lodash.pullAt = array.pullAt; +lodash.range = util.range; +lodash.rangeRight = util.rangeRight; +lodash.rearg = func.rearg; +lodash.reject = collection.reject; +lodash.remove = array.remove; +lodash.rest = rest; +lodash.reverse = array.reverse; +lodash.sampleSize = collection.sampleSize; +lodash.set = object.set; +lodash.setWith = object.setWith; +lodash.shuffle = collection.shuffle; +lodash.slice = array.slice; +lodash.sortBy = collection.sortBy; +lodash.sortedUniq = array.sortedUniq; +lodash.sortedUniqBy = array.sortedUniqBy; +lodash.split = string.split; +lodash.spread = func.spread; +lodash.tail = array.tail; +lodash.take = array.take; +lodash.takeRight = array.takeRight; +lodash.takeRightWhile = array.takeRightWhile; +lodash.takeWhile = array.takeWhile; +lodash.tap = seq.tap; +lodash.throttle = func.throttle; +lodash.thru = thru; +lodash.toArray = lang.toArray; +lodash.toPairs = object.toPairs; +lodash.toPairsIn = object.toPairsIn; +lodash.toPath = util.toPath; +lodash.toPlainObject = lang.toPlainObject; +lodash.transform = object.transform; +lodash.unary = func.unary; +lodash.union = array.union; +lodash.unionBy = array.unionBy; +lodash.unionWith = array.unionWith; +lodash.uniq = array.uniq; +lodash.uniqBy = array.uniqBy; +lodash.uniqWith = array.uniqWith; +lodash.unset = object.unset; +lodash.unzip = array.unzip; +lodash.unzipWith = array.unzipWith; +lodash.values = object.values; +lodash.valuesIn = object.valuesIn; +lodash.without = array.without; +lodash.words = string.words; +lodash.wrap = func.wrap; +lodash.xor = array.xor; +lodash.xorBy = array.xorBy; +lodash.xorWith = array.xorWith; +lodash.zip = array.zip; +lodash.zipObject = array.zipObject; +lodash.zipWith = array.zipWith; + +// Add aliases. +lodash.each = collection.forEach; +lodash.eachRight = collection.forEachRight; +lodash.extend = object.assignIn; +lodash.extendWith = object.assignInWith; + +// Add functions to `lodash.prototype`. +mixin(lodash, lodash); + +// Add functions that return unwrapped values when chaining. +lodash.add = math.add; +lodash.attempt = util.attempt; +lodash.camelCase = string.camelCase; +lodash.capitalize = string.capitalize; +lodash.ceil = math.ceil; +lodash.clamp = number.clamp; +lodash.clone = lang.clone; +lodash.cloneDeep = lang.cloneDeep; +lodash.cloneDeepWith = lang.cloneDeepWith; +lodash.cloneWith = lang.cloneWith; +lodash.deburr = string.deburr; +lodash.endsWith = string.endsWith; +lodash.eq = lang.eq; +lodash.escape = string.escape; +lodash.escapeRegExp = string.escapeRegExp; +lodash.every = collection.every; +lodash.find = collection.find; +lodash.findIndex = array.findIndex; +lodash.findKey = object.findKey; +lodash.findLast = collection.findLast; +lodash.findLastIndex = array.findLastIndex; +lodash.findLastKey = object.findLastKey; +lodash.floor = math.floor; +lodash.forEach = collection.forEach; +lodash.forEachRight = collection.forEachRight; +lodash.forIn = object.forIn; +lodash.forInRight = object.forInRight; +lodash.forOwn = object.forOwn; +lodash.forOwnRight = object.forOwnRight; +lodash.get = object.get; +lodash.gt = lang.gt; +lodash.gte = lang.gte; +lodash.has = object.has; +lodash.hasIn = object.hasIn; +lodash.head = array.head; +lodash.identity = identity; +lodash.includes = collection.includes; +lodash.indexOf = array.indexOf; +lodash.inRange = number.inRange; +lodash.invoke = object.invoke; +lodash.isArguments = lang.isArguments; +lodash.isArray = isArray; +lodash.isArrayLike = lang.isArrayLike; +lodash.isArrayLikeObject = lang.isArrayLikeObject; +lodash.isBoolean = lang.isBoolean; +lodash.isDate = lang.isDate; +lodash.isElement = lang.isElement; +lodash.isEmpty = lang.isEmpty; +lodash.isEqual = lang.isEqual; +lodash.isEqualWith = lang.isEqualWith; +lodash.isError = lang.isError; +lodash.isFinite = lang.isFinite; +lodash.isFunction = lang.isFunction; +lodash.isInteger = lang.isInteger; +lodash.isLength = lang.isLength; +lodash.isMatch = lang.isMatch; +lodash.isMatchWith = lang.isMatchWith; +lodash.isNaN = lang.isNaN; +lodash.isNative = lang.isNative; +lodash.isNil = lang.isNil; +lodash.isNull = lang.isNull; +lodash.isNumber = lang.isNumber; +lodash.isObject = isObject; +lodash.isObjectLike = lang.isObjectLike; +lodash.isPlainObject = lang.isPlainObject; +lodash.isRegExp = lang.isRegExp; +lodash.isSafeInteger = lang.isSafeInteger; +lodash.isString = lang.isString; +lodash.isSymbol = lang.isSymbol; +lodash.isTypedArray = lang.isTypedArray; +lodash.isUndefined = lang.isUndefined; +lodash.join = array.join; +lodash.kebabCase = string.kebabCase; +lodash.last = last; +lodash.lastIndexOf = array.lastIndexOf; +lodash.lowerCase = string.lowerCase; +lodash.lowerFirst = string.lowerFirst; +lodash.lt = lang.lt; +lodash.lte = lang.lte; +lodash.max = math.max; +lodash.maxBy = math.maxBy; +lodash.mean = math.mean; +lodash.min = math.min; +lodash.minBy = math.minBy; +lodash.noop = util.noop; +lodash.now = date.now; +lodash.pad = string.pad; +lodash.padEnd = string.padEnd; +lodash.padStart = string.padStart; +lodash.parseInt = string.parseInt; +lodash.random = number.random; +lodash.reduce = collection.reduce; +lodash.reduceRight = collection.reduceRight; +lodash.repeat = string.repeat; +lodash.replace = string.replace; +lodash.result = object.result; +lodash.round = math.round; +lodash.sample = collection.sample; +lodash.size = collection.size; +lodash.snakeCase = string.snakeCase; +lodash.some = collection.some; +lodash.sortedIndex = array.sortedIndex; +lodash.sortedIndexBy = array.sortedIndexBy; +lodash.sortedIndexOf = array.sortedIndexOf; +lodash.sortedLastIndex = array.sortedLastIndex; +lodash.sortedLastIndexBy = array.sortedLastIndexBy; +lodash.sortedLastIndexOf = array.sortedLastIndexOf; +lodash.startCase = string.startCase; +lodash.startsWith = string.startsWith; +lodash.subtract = math.subtract; +lodash.sum = math.sum; +lodash.sumBy = math.sumBy; +lodash.template = string.template; +lodash.times = util.times; +lodash.toInteger = toInteger; +lodash.toLength = lang.toLength; +lodash.toLower = string.toLower; +lodash.toNumber = lang.toNumber; +lodash.toSafeInteger = lang.toSafeInteger; +lodash.toString = lang.toString; +lodash.toUpper = string.toUpper; +lodash.trim = string.trim; +lodash.trimEnd = string.trimEnd; +lodash.trimStart = string.trimStart; +lodash.truncate = string.truncate; +lodash.unescape = string.unescape; +lodash.uniqueId = util.uniqueId; +lodash.upperCase = string.upperCase; +lodash.upperFirst = string.upperFirst; + +// Add aliases. +lodash.first = array.head; + +mixin(lodash, (function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!hasOwnProperty.call(lodash.prototype, methodName)) { + source[methodName] = func; + } + }); + return source; +}()), { 'chain': false }); + +/** + * The semantic version number. + * + * @static + * @memberOf _ + * @type string + */ +lodash.VERSION = VERSION; +(lodash.templateSettings = string.templateSettings).imports._ = lodash; + +// Assign default placeholders. +arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) { + lodash[methodName].placeholder = lodash; +}); + +// Add `LazyWrapper` methods for `_.drop` and `_.take` variants. +arrayEach(['drop', 'take'], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n === undefined ? 1 : nativeMax(toInteger(n), 0); + + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(n, result.__takeCount__); + } else { + result.__views__.push({ 'size': nativeMin(n, MAX_ARRAY_LENGTH), 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); + } + return result; + }; + + LazyWrapper.prototype[methodName + 'Right'] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; +}); + +// Add `LazyWrapper` methods that accept an `iteratee` value. +arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { + var type = index + 1, + isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG; + + LazyWrapper.prototype[methodName] = function(iteratee) { + var result = this.clone(); + result.__iteratees__.push({ 'iteratee': baseIteratee(iteratee, 3), 'type': type }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; +}); + +// Add `LazyWrapper` methods for `_.head` and `_.last`. +arrayEach(['head', 'last'], function(methodName, index) { + var takeName = 'take' + (index ? 'Right' : ''); + + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; +}); + +// Add `LazyWrapper` methods for `_.initial` and `_.tail`. +arrayEach(['initial', 'tail'], function(methodName, index) { + var dropName = 'drop' + (index ? '' : 'Right'); + + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; +}); + +LazyWrapper.prototype.compact = function() { + return this.filter(identity); +}; + +LazyWrapper.prototype.find = function(predicate) { + return this.filter(predicate).head(); +}; + +LazyWrapper.prototype.findLast = function(predicate) { + return this.reverse().find(predicate); +}; + +LazyWrapper.prototype.invokeMap = rest(function(path, args) { + if (typeof path == 'function') { + return new LazyWrapper(this); + } + return this.map(function(value) { + return baseInvoke(value, path, args); + }); +}); + +LazyWrapper.prototype.reject = function(predicate) { + predicate = baseIteratee(predicate, 3); + return this.filter(function(value) { + return !predicate(value); + }); +}; + +LazyWrapper.prototype.slice = function(start, end) { + start = toInteger(start); + + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = toInteger(end); + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; +}; + +LazyWrapper.prototype.takeRightWhile = function(predicate) { + return this.reverse().takeWhile(predicate).reverse(); +}; + +LazyWrapper.prototype.toArray = function() { + return this.take(MAX_ARRAY_LENGTH); +}; + +// Add `LazyWrapper` methods to `lodash.prototype`. +baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), + isTaker = /^(?:head|last)$/.test(methodName), + lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName], + retUnwrapped = isTaker || /^find/.test(methodName); + + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var value = this.__wrapped__, + args = isTaker ? [1] : arguments, + isLazy = value instanceof LazyWrapper, + iteratee = args[0], + useLazy = isLazy || isArray(value); + + var interceptor = function(value) { + var result = lodashFunc.apply(lodash, arrayPush([value], args)); + return (isTaker && chainAll) ? result[0] : result; + }; + + if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { + // Avoid lazy use if the iteratee has a "length" value other than `1`. + isLazy = useLazy = false; + } + var chainAll = this.__chain__, + isHybrid = !!this.__actions__.length, + isUnwrapped = retUnwrapped && !chainAll, + onlyLazy = isLazy && !isHybrid; + + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + return new LodashWrapper(result, chainAll); + } + if (isUnwrapped && onlyLazy) { + return func.apply(this, args); + } + result = this.thru(interceptor); + return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result; + }; +}); + +// Add `Array` and `String` methods to `lodash.prototype`. +arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var func = arrayProto[methodName], + chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', + retUnwrapped = /^(?:pop|shift)$/.test(methodName); + + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; +}); + +// 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(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }]; + +// Add functions to the lazy wrapper. +LazyWrapper.prototype.clone = lazyClone; +LazyWrapper.prototype.reverse = lazyReverse; +LazyWrapper.prototype.value = lazyValue; + +// Add chaining functions to the `lodash` wrapper. +lodash.prototype.at = seq.at; +lodash.prototype.chain = seq.wrapperChain; +lodash.prototype.commit = seq.commit; +lodash.prototype.flatMap = seq.flatMap; +lodash.prototype.next = seq.next; +lodash.prototype.plant = seq.plant; +lodash.prototype.reverse = seq.reverse; +lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = seq.value; + +if (iteratorSymbol) { + lodash.prototype[iteratorSymbol] = seq.toIterator; +} + +export default lodash; diff --git a/lodash.js b/lodash.js index dd45ef96b..f65170e3b 100644 --- a/lodash.js +++ b/lodash.js @@ -1,551 +1,299 @@ /** * @license - * lodash 3.10.1 (Custom Build) - * Build: `lodash modularize modern exports="es" -o ./` - * Copyright 2012-2015 The Dojo Foundation + * lodash 4.0.0 (Custom Build) + * Build: `lodash modularize exports="es" -o ./` + * Copyright 2012-2016 The Dojo Foundation * Based on Underscore.js 1.8.3 - * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ -import array from './array'; -import chain from './chain'; -import collection from './collection'; -import date from './date'; -import func from './function'; -import lang from './lang'; -import math from './math'; -import number from './number'; -import object from './object'; -import string from './string'; -import utility from './utility'; -import LazyWrapper from './internal/LazyWrapper'; -import LodashWrapper from './internal/LodashWrapper'; -import arrayEach from './internal/arrayEach'; -import arrayPush from './internal/arrayPush'; -import baseCallback from './internal/baseCallback'; -import baseForOwn from './internal/baseForOwn'; -import baseFunctions from './internal/baseFunctions'; -import baseMatches from './internal/baseMatches'; -import createHybridWrapper from './internal/createHybridWrapper'; -import identity from './utility/identity'; -import isArray from './lang/isArray'; -import isObject from './lang/isObject'; -import keys from './object/keys'; -import last from './array/last'; -import lazyClone from './internal/lazyClone'; -import lazyReverse from './internal/lazyReverse'; -import lazyValue from './internal/lazyValue'; -import lodash from './chain/lodash'; -import _mixin from './utility/mixin'; -import property from './utility/property'; -import realNames from './internal/realNames'; -import support from './support'; -import thru from './chain/thru'; - -/** Used as the semantic version number. */ -var VERSION = '3.10.1'; - -/** Used to compose bitmasks for wrapper metadata. */ -var BIND_KEY_FLAG = 2; - -/** Used to indicate the type of lazy iteratees. */ -var LAZY_MAP_FLAG = 2; - -/** Used for native method references. */ -var arrayProto = Array.prototype, - stringProto = String.prototype; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeFloor = Math.floor, - nativeMax = Math.max, - nativeMin = Math.min; - -/** Used as references for `-Infinity` and `Infinity`. */ -var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; - -// wrap `_.mixin` so it works when provided only one argument -var mixin = (function(func) { - return function(object, source, options) { - if (options == null) { - var isObj = isObject(source), - props = isObj && keys(source), - methodNames = props && props.length && baseFunctions(source, props); - - if (!(methodNames ? methodNames.length : isObj)) { - options = source; - source = object; - object = this; - } - } - return func(object, source, options); - }; -}(_mixin)); - -// Add functions that return wrapped values when chaining. -lodash.after = func.after; -lodash.ary = func.ary; -lodash.assign = object.assign; -lodash.at = collection.at; -lodash.before = func.before; -lodash.bind = func.bind; -lodash.bindAll = func.bindAll; -lodash.bindKey = func.bindKey; -lodash.callback = utility.callback; -lodash.chain = chain.chain; -lodash.chunk = array.chunk; -lodash.compact = array.compact; -lodash.constant = utility.constant; -lodash.countBy = collection.countBy; -lodash.create = object.create; -lodash.curry = func.curry; -lodash.curryRight = func.curryRight; -lodash.debounce = func.debounce; -lodash.defaults = object.defaults; -lodash.defaultsDeep = object.defaultsDeep; -lodash.defer = func.defer; -lodash.delay = func.delay; -lodash.difference = array.difference; -lodash.drop = array.drop; -lodash.dropRight = array.dropRight; -lodash.dropRightWhile = array.dropRightWhile; -lodash.dropWhile = array.dropWhile; -lodash.fill = array.fill; -lodash.filter = collection.filter; -lodash.flatten = array.flatten; -lodash.flattenDeep = array.flattenDeep; -lodash.flow = func.flow; -lodash.flowRight = func.flowRight; -lodash.forEach = collection.forEach; -lodash.forEachRight = collection.forEachRight; -lodash.forIn = object.forIn; -lodash.forInRight = object.forInRight; -lodash.forOwn = object.forOwn; -lodash.forOwnRight = object.forOwnRight; -lodash.functions = object.functions; -lodash.groupBy = collection.groupBy; -lodash.indexBy = collection.indexBy; -lodash.initial = array.initial; -lodash.intersection = array.intersection; -lodash.invert = object.invert; -lodash.invoke = collection.invoke; -lodash.keys = keys; -lodash.keysIn = object.keysIn; -lodash.map = collection.map; -lodash.mapKeys = object.mapKeys; -lodash.mapValues = object.mapValues; -lodash.matches = utility.matches; -lodash.matchesProperty = utility.matchesProperty; -lodash.memoize = func.memoize; -lodash.merge = object.merge; -lodash.method = utility.method; -lodash.methodOf = utility.methodOf; -lodash.mixin = mixin; -lodash.modArgs = func.modArgs; -lodash.negate = func.negate; -lodash.omit = object.omit; -lodash.once = func.once; -lodash.pairs = object.pairs; -lodash.partial = func.partial; -lodash.partialRight = func.partialRight; -lodash.partition = collection.partition; -lodash.pick = object.pick; -lodash.pluck = collection.pluck; -lodash.property = property; -lodash.propertyOf = utility.propertyOf; -lodash.pull = array.pull; -lodash.pullAt = array.pullAt; -lodash.range = utility.range; -lodash.rearg = func.rearg; -lodash.reject = collection.reject; -lodash.remove = array.remove; -lodash.rest = array.rest; -lodash.restParam = func.restParam; -lodash.set = object.set; -lodash.shuffle = collection.shuffle; -lodash.slice = array.slice; -lodash.sortBy = collection.sortBy; -lodash.sortByAll = collection.sortByAll; -lodash.sortByOrder = collection.sortByOrder; -lodash.spread = func.spread; -lodash.take = array.take; -lodash.takeRight = array.takeRight; -lodash.takeRightWhile = array.takeRightWhile; -lodash.takeWhile = array.takeWhile; -lodash.tap = chain.tap; -lodash.throttle = func.throttle; -lodash.thru = thru; -lodash.times = utility.times; -lodash.toArray = lang.toArray; -lodash.toPlainObject = lang.toPlainObject; -lodash.transform = object.transform; -lodash.union = array.union; -lodash.uniq = array.uniq; -lodash.unzip = array.unzip; -lodash.unzipWith = array.unzipWith; -lodash.values = object.values; -lodash.valuesIn = object.valuesIn; -lodash.where = collection.where; -lodash.without = array.without; -lodash.wrap = func.wrap; -lodash.xor = array.xor; -lodash.zip = array.zip; -lodash.zipObject = array.zipObject; -lodash.zipWith = array.zipWith; - -// Add aliases. -lodash.backflow = func.flowRight; -lodash.collect = collection.map; -lodash.compose = func.flowRight; -lodash.each = collection.forEach; -lodash.eachRight = collection.forEachRight; -lodash.extend = object.assign; -lodash.iteratee = utility.callback; -lodash.methods = object.functions; -lodash.object = array.zipObject; -lodash.select = collection.filter; -lodash.tail = array.rest; -lodash.unique = array.uniq; - -// Add functions to `lodash.prototype`. -mixin(lodash, lodash); - -// Add functions that return unwrapped values when chaining. -lodash.add = math.add; -lodash.attempt = utility.attempt; -lodash.camelCase = string.camelCase; -lodash.capitalize = string.capitalize; -lodash.ceil = math.ceil; -lodash.clone = lang.clone; -lodash.cloneDeep = lang.cloneDeep; -lodash.deburr = string.deburr; -lodash.endsWith = string.endsWith; -lodash.escape = string.escape; -lodash.escapeRegExp = string.escapeRegExp; -lodash.every = collection.every; -lodash.find = collection.find; -lodash.findIndex = array.findIndex; -lodash.findKey = object.findKey; -lodash.findLast = collection.findLast; -lodash.findLastIndex = array.findLastIndex; -lodash.findLastKey = object.findLastKey; -lodash.findWhere = collection.findWhere; -lodash.first = array.first; -lodash.floor = math.floor; -lodash.get = object.get; -lodash.gt = lang.gt; -lodash.gte = lang.gte; -lodash.has = object.has; -lodash.identity = identity; -lodash.includes = collection.includes; -lodash.indexOf = array.indexOf; -lodash.inRange = number.inRange; -lodash.isArguments = lang.isArguments; -lodash.isArray = isArray; -lodash.isBoolean = lang.isBoolean; -lodash.isDate = lang.isDate; -lodash.isElement = lang.isElement; -lodash.isEmpty = lang.isEmpty; -lodash.isEqual = lang.isEqual; -lodash.isError = lang.isError; -lodash.isFinite = lang.isFinite; -lodash.isFunction = lang.isFunction; -lodash.isMatch = lang.isMatch; -lodash.isNaN = lang.isNaN; -lodash.isNative = lang.isNative; -lodash.isNull = lang.isNull; -lodash.isNumber = lang.isNumber; -lodash.isObject = isObject; -lodash.isPlainObject = lang.isPlainObject; -lodash.isRegExp = lang.isRegExp; -lodash.isString = lang.isString; -lodash.isTypedArray = lang.isTypedArray; -lodash.isUndefined = lang.isUndefined; -lodash.kebabCase = string.kebabCase; -lodash.last = last; -lodash.lastIndexOf = array.lastIndexOf; -lodash.lt = lang.lt; -lodash.lte = lang.lte; -lodash.max = math.max; -lodash.min = math.min; -lodash.noop = utility.noop; -lodash.now = date.now; -lodash.pad = string.pad; -lodash.padLeft = string.padLeft; -lodash.padRight = string.padRight; -lodash.parseInt = string.parseInt; -lodash.random = number.random; -lodash.reduce = collection.reduce; -lodash.reduceRight = collection.reduceRight; -lodash.repeat = string.repeat; -lodash.result = object.result; -lodash.round = math.round; -lodash.size = collection.size; -lodash.snakeCase = string.snakeCase; -lodash.some = collection.some; -lodash.sortedIndex = array.sortedIndex; -lodash.sortedLastIndex = array.sortedLastIndex; -lodash.startCase = string.startCase; -lodash.startsWith = string.startsWith; -lodash.sum = math.sum; -lodash.template = string.template; -lodash.trim = string.trim; -lodash.trimLeft = string.trimLeft; -lodash.trimRight = string.trimRight; -lodash.trunc = string.trunc; -lodash.unescape = string.unescape; -lodash.uniqueId = utility.uniqueId; -lodash.words = string.words; - -// Add aliases. -lodash.all = collection.every; -lodash.any = collection.some; -lodash.contains = collection.includes; -lodash.eq = lang.isEqual; -lodash.detect = collection.find; -lodash.foldl = collection.reduce; -lodash.foldr = collection.reduceRight; -lodash.head = array.first; -lodash.include = collection.includes; -lodash.inject = collection.reduce; - -mixin(lodash, (function() { - var source = {}; - baseForOwn(lodash, function(func, methodName) { - if (!lodash.prototype[methodName]) { - source[methodName] = func; - } - }); - return source; -}()), false); - -// Add functions capable of returning wrapped and unwrapped values when chaining. -lodash.sample = collection.sample; - -lodash.prototype.sample = function(n) { - if (!this.__chain__ && n == null) { - return collection.sample(this.value()); - } - return this.thru(function(value) { - return collection.sample(value, n); - }); -}; - -/** - * The semantic version number. - * - * @static - * @memberOf _ - * @type string - */ -lodash.VERSION = VERSION; - -lodash.support = support; -(lodash.templateSettings = string.templateSettings).imports._ = lodash; - -// Assign default placeholders. -arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) { - lodash[methodName].placeholder = lodash; -}); - -// Add `LazyWrapper` methods for `_.drop` and `_.take` variants. -arrayEach(['drop', 'take'], function(methodName, index) { - LazyWrapper.prototype[methodName] = function(n) { - var filtered = this.__filtered__; - if (filtered && !index) { - return new LazyWrapper(this); - } - n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); - - var result = this.clone(); - if (filtered) { - result.__takeCount__ = nativeMin(result.__takeCount__, n); - } else { - result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') }); - } - return result; - }; - - LazyWrapper.prototype[methodName + 'Right'] = function(n) { - return this.reverse()[methodName](n).reverse(); - }; -}); - -// Add `LazyWrapper` methods that accept an `iteratee` value. -arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { - var type = index + 1, - isFilter = type != LAZY_MAP_FLAG; - - LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { - var result = this.clone(); - result.__iteratees__.push({ 'iteratee': baseCallback(iteratee, thisArg, 1), 'type': type }); - result.__filtered__ = result.__filtered__ || isFilter; - return result; - }; -}); - -// Add `LazyWrapper` methods for `_.first` and `_.last`. -arrayEach(['first', 'last'], function(methodName, index) { - var takeName = 'take' + (index ? 'Right' : ''); - - LazyWrapper.prototype[methodName] = function() { - return this[takeName](1).value()[0]; - }; -}); - -// Add `LazyWrapper` methods for `_.initial` and `_.rest`. -arrayEach(['initial', 'rest'], function(methodName, index) { - var dropName = 'drop' + (index ? '' : 'Right'); - - LazyWrapper.prototype[methodName] = function() { - return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); - }; -}); - -// Add `LazyWrapper` methods for `_.pluck` and `_.where`. -arrayEach(['pluck', 'where'], function(methodName, index) { - var operationName = index ? 'filter' : 'map', - createCallback = index ? baseMatches : property; - - LazyWrapper.prototype[methodName] = function(value) { - return this[operationName](createCallback(value)); - }; -}); - -LazyWrapper.prototype.compact = function() { - return this.filter(identity); -}; - -LazyWrapper.prototype.reject = function(predicate, thisArg) { - predicate = baseCallback(predicate, thisArg, 1); - return this.filter(function(value) { - return !predicate(value); - }); -}; - -LazyWrapper.prototype.slice = function(start, end) { - start = start == null ? 0 : (+start || 0); - - var result = this; - if (result.__filtered__ && (start > 0 || end < 0)) { - return new LazyWrapper(result); - } - if (start < 0) { - result = result.takeRight(-start); - } else if (start) { - result = result.drop(start); - } - if (end !== undefined) { - end = (+end || 0); - result = end < 0 ? result.dropRight(-end) : result.take(end - start); - } - return result; -}; - -LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { - return this.reverse().takeWhile(predicate, thisArg).reverse(); -}; - -LazyWrapper.prototype.toArray = function() { - return this.take(POSITIVE_INFINITY); -}; - -// Add `LazyWrapper` methods to `lodash.prototype`. -baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), - retUnwrapped = /^(?:first|last)$/.test(methodName), - lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName]; - - if (!lodashFunc) { - return; - } - lodash.prototype[methodName] = function() { - var args = retUnwrapped ? [1] : arguments, - chainAll = this.__chain__, - value = this.__wrapped__, - isHybrid = !!this.__actions__.length, - isLazy = value instanceof LazyWrapper, - iteratee = args[0], - useLazy = isLazy || isArray(value); - - if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { - // Avoid lazy use if the iteratee has a "length" value other than `1`. - isLazy = useLazy = false; - } - var interceptor = function(value) { - return (retUnwrapped && chainAll) - ? lodashFunc(value, 1)[0] - : lodashFunc.apply(undefined, arrayPush([value], args)); - }; - - var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined }, - onlyLazy = isLazy && !isHybrid; - - if (retUnwrapped && !chainAll) { - if (onlyLazy) { - value = value.clone(); - value.__actions__.push(action); - return func.call(value); - } - return lodashFunc.call(undefined, this.value())[0]; - } - if (!retUnwrapped && useLazy) { - value = onlyLazy ? value : new LazyWrapper(this); - var result = func.apply(value, args); - result.__actions__.push(action); - return new LodashWrapper(result, chainAll); - } - return this.thru(interceptor); - }; -}); - -// Add `Array` and `String` methods to `lodash.prototype`. -arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) { - var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], - chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', - retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); - - lodash.prototype[methodName] = function() { - var args = arguments; - if (retUnwrapped && !this.__chain__) { - return func.apply(this.value(), args); - } - return this[chainName](function(value) { - return func.apply(value, args); - }); - }; -}); - -// 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(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }]; - -// Add functions to the lazy wrapper. -LazyWrapper.prototype.clone = lazyClone; -LazyWrapper.prototype.reverse = lazyReverse; -LazyWrapper.prototype.value = lazyValue; - -// Add chaining functions to the `lodash` wrapper. -lodash.prototype.chain = chain.wrapperChain; -lodash.prototype.commit = chain.commit; -lodash.prototype.concat = chain.concat; -lodash.prototype.plant = chain.plant; -lodash.prototype.reverse = chain.reverse; -lodash.prototype.toString = chain.toString; -lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = chain.value; - -// Add function aliases to the `lodash` wrapper. -lodash.prototype.collect = lodash.prototype.map; -lodash.prototype.head = lodash.prototype.first; -lodash.prototype.select = lodash.prototype.filter; -lodash.prototype.tail = lodash.prototype.rest; - -export default lodash; +export { default as add } from './add'; +export { default as after } from './after'; +export { default as ary } from './ary'; +export { default as assign } from './assign'; +export { default as assignIn } from './assignIn'; +export { default as assignInWith } from './assignInWith'; +export { default as assignWith } from './assignWith'; +export { default as at } from './at'; +export { default as attempt } from './attempt'; +export { default as before } from './before'; +export { default as bind } from './bind'; +export { default as bindAll } from './bindAll'; +export { default as bindKey } from './bindKey'; +export { default as camelCase } from './camelCase'; +export { default as capitalize } from './capitalize'; +export { default as ceil } from './ceil'; +export { default as chain } from './chain'; +export { default as chunk } from './chunk'; +export { default as clamp } from './clamp'; +export { default as clone } from './clone'; +export { default as cloneDeep } from './cloneDeep'; +export { default as cloneDeepWith } from './cloneDeepWith'; +export { default as cloneWith } from './cloneWith'; +export { default as commit } from './commit'; +export { default as compact } from './compact'; +export { default as concat } from './concat'; +export { default as cond } from './cond'; +export { default as conforms } from './conforms'; +export { default as constant } from './constant'; +export { default as countBy } from './countBy'; +export { default as create } from './create'; +export { default as curry } from './curry'; +export { default as curryRight } from './curryRight'; +export { default as debounce } from './debounce'; +export { default as deburr } from './deburr'; +export { default as defaults } from './defaults'; +export { default as defaultsDeep } from './defaultsDeep'; +export { default as defer } from './defer'; +export { default as delay } from './delay'; +export { default as difference } from './difference'; +export { default as differenceBy } from './differenceBy'; +export { default as differenceWith } from './differenceWith'; +export { default as drop } from './drop'; +export { default as dropRight } from './dropRight'; +export { default as dropRightWhile } from './dropRightWhile'; +export { default as dropWhile } from './dropWhile'; +export { default as each } from './each'; +export { default as eachRight } from './eachRight'; +export { default as endsWith } from './endsWith'; +export { default as eq } from './eq'; +export { default as escape } from './escape'; +export { default as escapeRegExp } from './escapeRegExp'; +export { default as every } from './every'; +export { default as fill } from './fill'; +export { default as filter } from './filter'; +export { default as find } from './find'; +export { default as findIndex } from './findIndex'; +export { default as findKey } from './findKey'; +export { default as findLast } from './findLast'; +export { default as findLastIndex } from './findLastIndex'; +export { default as findLastKey } from './findLastKey'; +export { default as flatMap } from './flatMap'; +export { default as flatten } from './flatten'; +export { default as flattenDeep } from './flattenDeep'; +export { default as flip } from './flip'; +export { default as floor } from './floor'; +export { default as flow } from './flow'; +export { default as flowRight } from './flowRight'; +export { default as forEach } from './forEach'; +export { default as forEachRight } from './forEachRight'; +export { default as forIn } from './forIn'; +export { default as forInRight } from './forInRight'; +export { default as forOwn } from './forOwn'; +export { default as forOwnRight } from './forOwnRight'; +export { default as fromPairs } from './fromPairs'; +export { default as functions } from './functions'; +export { default as functionsIn } from './functionsIn'; +export { default as get } from './get'; +export { default as groupBy } from './groupBy'; +export { default as gt } from './gt'; +export { default as gte } from './gte'; +export { default as has } from './has'; +export { default as hasIn } from './hasIn'; +export { default as head } from './head'; +export { default as identity } from './identity'; +export { default as inRange } from './inRange'; +export { default as includes } from './includes'; +export { default as indexOf } from './indexOf'; +export { default as initial } from './initial'; +export { default as intersection } from './intersection'; +export { default as intersectionBy } from './intersectionBy'; +export { default as intersectionWith } from './intersectionWith'; +export { default as invert } from './invert'; +export { default as invoke } from './invoke'; +export { default as invokeMap } from './invokeMap'; +export { default as isArguments } from './isArguments'; +export { default as isArray } from './isArray'; +export { default as isArrayLike } from './isArrayLike'; +export { default as isArrayLikeObject } from './isArrayLikeObject'; +export { default as isBoolean } from './isBoolean'; +export { default as isDate } from './isDate'; +export { default as isElement } from './isElement'; +export { default as isEmpty } from './isEmpty'; +export { default as isEqual } from './isEqual'; +export { default as isEqualWith } from './isEqualWith'; +export { default as isError } from './isError'; +export { default as isFinite } from './isFinite'; +export { default as isFunction } from './isFunction'; +export { default as isInteger } from './isInteger'; +export { default as isLength } from './isLength'; +export { default as isMatch } from './isMatch'; +export { default as isMatchWith } from './isMatchWith'; +export { default as isNaN } from './isNaN'; +export { default as isNative } from './isNative'; +export { default as isNil } from './isNil'; +export { default as isNull } from './isNull'; +export { default as isNumber } from './isNumber'; +export { default as isObject } from './isObject'; +export { default as isObjectLike } from './isObjectLike'; +export { default as isPlainObject } from './isPlainObject'; +export { default as isRegExp } from './isRegExp'; +export { default as isSafeInteger } from './isSafeInteger'; +export { default as isString } from './isString'; +export { default as isSymbol } from './isSymbol'; +export { default as isTypedArray } from './isTypedArray'; +export { default as isUndefined } from './isUndefined'; +export { default as iteratee } from './iteratee'; +export { default as join } from './join'; +export { default as kebabCase } from './kebabCase'; +export { default as keyBy } from './keyBy'; +export { default as keys } from './keys'; +export { default as keysIn } from './keysIn'; +export { default as last } from './last'; +export { default as lastIndexOf } from './lastIndexOf'; +export { default as lodash } from './wrapperLodash'; +export { default as lowerCase } from './lowerCase'; +export { default as lowerFirst } from './lowerFirst'; +export { default as lt } from './lt'; +export { default as lte } from './lte'; +export { default as map } from './map'; +export { default as mapKeys } from './mapKeys'; +export { default as mapValues } from './mapValues'; +export { default as matches } from './matches'; +export { default as matchesProperty } from './matchesProperty'; +export { default as max } from './max'; +export { default as maxBy } from './maxBy'; +export { default as mean } from './mean'; +export { default as memoize } from './memoize'; +export { default as merge } from './merge'; +export { default as mergeWith } from './mergeWith'; +export { default as method } from './method'; +export { default as methodOf } from './methodOf'; +export { default as min } from './min'; +export { default as minBy } from './minBy'; +export { default as mixin } from './mixin'; +export { default as negate } from './negate'; +export { default as next } from './next'; +export { default as noop } from './noop'; +export { default as now } from './now'; +export { default as nthArg } from './nthArg'; +export { default as omit } from './omit'; +export { default as omitBy } from './omitBy'; +export { default as once } from './once'; +export { default as orderBy } from './orderBy'; +export { default as over } from './over'; +export { default as overArgs } from './overArgs'; +export { default as overEvery } from './overEvery'; +export { default as overSome } from './overSome'; +export { default as pad } from './pad'; +export { default as padEnd } from './padEnd'; +export { default as padStart } from './padStart'; +export { default as parseInt } from './parseInt'; +export { default as partial } from './partial'; +export { default as partialRight } from './partialRight'; +export { default as partition } from './partition'; +export { default as pick } from './pick'; +export { default as pickBy } from './pickBy'; +export { default as plant } from './plant'; +export { default as property } from './property'; +export { default as propertyOf } from './propertyOf'; +export { default as pull } from './pull'; +export { default as pullAll } from './pullAll'; +export { default as pullAllBy } from './pullAllBy'; +export { default as pullAt } from './pullAt'; +export { default as random } from './random'; +export { default as range } from './range'; +export { default as rangeRight } from './rangeRight'; +export { default as rearg } from './rearg'; +export { default as reduce } from './reduce'; +export { default as reduceRight } from './reduceRight'; +export { default as reject } from './reject'; +export { default as remove } from './remove'; +export { default as repeat } from './repeat'; +export { default as replace } from './replace'; +export { default as rest } from './rest'; +export { default as result } from './result'; +export { default as reverse } from './reverse'; +export { default as round } from './round'; +export { default as sample } from './sample'; +export { default as sampleSize } from './sampleSize'; +export { default as set } from './set'; +export { default as setWith } from './setWith'; +export { default as shuffle } from './shuffle'; +export { default as size } from './size'; +export { default as slice } from './slice'; +export { default as snakeCase } from './snakeCase'; +export { default as some } from './some'; +export { default as sortBy } from './sortBy'; +export { default as sortedIndex } from './sortedIndex'; +export { default as sortedIndexBy } from './sortedIndexBy'; +export { default as sortedIndexOf } from './sortedIndexOf'; +export { default as sortedLastIndex } from './sortedLastIndex'; +export { default as sortedLastIndexBy } from './sortedLastIndexBy'; +export { default as sortedLastIndexOf } from './sortedLastIndexOf'; +export { default as sortedUniq } from './sortedUniq'; +export { default as sortedUniqBy } from './sortedUniqBy'; +export { default as split } from './split'; +export { default as spread } from './spread'; +export { default as startCase } from './startCase'; +export { default as startsWith } from './startsWith'; +export { default as subtract } from './subtract'; +export { default as sum } from './sum'; +export { default as sumBy } from './sumBy'; +export { default as tail } from './tail'; +export { default as take } from './take'; +export { default as takeRight } from './takeRight'; +export { default as takeRightWhile } from './takeRightWhile'; +export { default as takeWhile } from './takeWhile'; +export { default as tap } from './tap'; +export { default as template } from './template'; +export { default as templateSettings } from './templateSettings'; +export { default as throttle } from './throttle'; +export { default as thru } from './thru'; +export { default as times } from './times'; +export { default as toArray } from './toArray'; +export { default as toInteger } from './toInteger'; +export { default as toIterator } from './toIterator'; +export { default as toJSON } from './toJSON'; +export { default as toLength } from './toLength'; +export { default as toLower } from './toLower'; +export { default as toNumber } from './toNumber'; +export { default as toPairs } from './toPairs'; +export { default as toPairsIn } from './toPairsIn'; +export { default as toPath } from './toPath'; +export { default as toPlainObject } from './toPlainObject'; +export { default as toSafeInteger } from './toSafeInteger'; +export { default as toString } from './toString'; +export { default as toUpper } from './toUpper'; +export { default as transform } from './transform'; +export { default as trim } from './trim'; +export { default as trimEnd } from './trimEnd'; +export { default as trimStart } from './trimStart'; +export { default as truncate } from './truncate'; +export { default as unary } from './unary'; +export { default as unescape } from './unescape'; +export { default as union } from './union'; +export { default as unionBy } from './unionBy'; +export { default as unionWith } from './unionWith'; +export { default as uniq } from './uniq'; +export { default as uniqBy } from './uniqBy'; +export { default as uniqWith } from './uniqWith'; +export { default as uniqueId } from './uniqueId'; +export { default as unset } from './unset'; +export { default as unzip } from './unzip'; +export { default as unzipWith } from './unzipWith'; +export { default as upperCase } from './upperCase'; +export { default as upperFirst } from './upperFirst'; +export { default as value } from './value'; +export { default as valueOf } from './valueOf'; +export { default as values } from './values'; +export { default as valuesIn } from './valuesIn'; +export { default as without } from './without'; +export { default as words } from './words'; +export { default as wrap } from './wrap'; +export { default as wrapperAt } from './wrapperAt'; +export { default as wrapperChain } from './wrapperChain'; +export { default as wrapperCommit } from './commit'; +export { default as wrapperFlatMap } from './wrapperFlatMap'; +export { default as wrapperNext } from './next'; +export { default as wrapperPlant } from './plant'; +export { default as wrapperReverse } from './wrapperReverse'; +export { default as wrapperToIterator } from './toIterator'; +export { default as wrapperValue } from './wrapperValue'; +export { default as xor } from './xor'; +export { default as xorBy } from './xorBy'; +export { default as xorWith } from './xorWith'; +export { default as zip } from './zip'; +export { default as zipObject } from './zipObject'; +export { default as zipWith } from './zipWith'; +export { default as default } from './lodash.default'; diff --git a/lowerCase.js b/lowerCase.js new file mode 100644 index 000000000..e06f7b18b --- /dev/null +++ b/lowerCase.js @@ -0,0 +1,26 @@ +import createCompounder from './internal/createCompounder'; + +/** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ +var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); +}); + +export default lowerCase; diff --git a/lowerFirst.js b/lowerFirst.js new file mode 100644 index 000000000..f5f6a4fc6 --- /dev/null +++ b/lowerFirst.js @@ -0,0 +1,21 @@ +import createCaseFirst from './internal/createCaseFirst'; + +/** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ +var lowerFirst = createCaseFirst('toLowerCase'); + +export default lowerFirst; diff --git a/lang/lt.js b/lt.js similarity index 100% rename from lang/lt.js rename to lt.js diff --git a/lang/lte.js b/lte.js similarity index 100% rename from lang/lte.js rename to lte.js diff --git a/map.js b/map.js new file mode 100644 index 000000000..cb5139a30 --- /dev/null +++ b/map.js @@ -0,0 +1,52 @@ +import arrayMap from './internal/arrayMap'; +import baseIteratee from './internal/baseIteratee'; +import baseMap from './internal/baseMap'; +import isArray from './isArray'; + +/** + * Creates an array of values by running each element in `collection` through + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, `fill`, + * `invert`, `parseInt`, `random`, `range`, `rangeRight`, `slice`, `some`, + * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimEnd`, `trimStart`, + * and `words` + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([1, 2], square); + * // => [3, 6] + * + * _.map({ 'a': 1, 'b': 2 }, square); + * // => [3, 6] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // using the `_.property` iteratee shorthand + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ +function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, baseIteratee(iteratee, 3)); +} + +export default map; diff --git a/object/mapKeys.js b/mapKeys.js similarity index 62% rename from object/mapKeys.js rename to mapKeys.js index ae66ea3c8..d1394242f 100644 --- a/object/mapKeys.js +++ b/mapKeys.js @@ -1,4 +1,5 @@ -import createObjectMapper from '../internal/createObjectMapper'; +import baseForOwn from './internal/baseForOwn'; +import baseIteratee from './internal/baseIteratee'; /** * The opposite of `_.mapValues`; this method creates an object with the @@ -9,9 +10,7 @@ import createObjectMapper from '../internal/createObjectMapper'; * @memberOf _ * @category Object * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns the new mapped object. * @example * @@ -20,6 +19,14 @@ import createObjectMapper from '../internal/createObjectMapper'; * }); * // => { 'a1': 1, 'b2': 2 } */ -var mapKeys = createObjectMapper(true); +function mapKeys(object, iteratee) { + var result = {}; + iteratee = baseIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + result[iteratee(value, key, object)] = value; + }); + return result; +} export default mapKeys; diff --git a/mapValues.js b/mapValues.js new file mode 100644 index 000000000..13e1c8326 --- /dev/null +++ b/mapValues.js @@ -0,0 +1,39 @@ +import baseForOwn from './internal/baseForOwn'; +import baseIteratee from './internal/baseIteratee'; + +/** + * 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 invoked with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // using the `_.property` iteratee shorthand + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ +function mapValues(object, iteratee) { + var result = {}; + iteratee = baseIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + result[key] = iteratee(value, key, object); + }); + return result; +} + +export default mapValues; diff --git a/matches.js b/matches.js new file mode 100644 index 000000000..e3b06506a --- /dev/null +++ b/matches.js @@ -0,0 +1,30 @@ +import baseClone from './internal/baseClone'; +import baseMatches from './internal/baseMatches'; + +/** + * Creates a function that performs a deep partial comparison between a given + * object and `source`, returning `true` if the given object has equivalent + * property values, else `false`. + * + * **Note:** This method supports comparing the same values as `_.isEqual`. + * + * @static + * @memberOf _ + * @category Util + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new function. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, _.matches({ 'age': 40, 'active': false })); + * // => [{ 'user': 'fred', 'age': 40, 'active': false }] + */ +function matches(source) { + return baseMatches(baseClone(source, true)); +} + +export default matches; diff --git a/utility/matchesProperty.js b/matchesProperty.js similarity index 53% rename from utility/matchesProperty.js rename to matchesProperty.js index 273d0ee6b..39a54663e 100644 --- a/utility/matchesProperty.js +++ b/matchesProperty.js @@ -1,17 +1,16 @@ -import baseClone from '../internal/baseClone'; -import baseMatchesProperty from '../internal/baseMatchesProperty'; +import baseClone from './internal/baseClone'; +import baseMatchesProperty from './internal/baseMatchesProperty'; /** - * Creates a function that compares the property value of `path` on a given - * object to `value`. + * Creates a function that performs a deep partial comparison between the + * value at `path` of a given object to `srcValue`, returning `true` if the + * object value is equivalent, else `false`. * - * **Note:** This method supports comparing arrays, booleans, `Date` objects, - * numbers, `Object` objects, regexes, and strings. Objects are compared by - * their own, not inherited, enumerable properties. + * **Note:** This method supports comparing the same values as `_.isEqual`. * * @static * @memberOf _ - * @category Utility + * @category Util * @param {Array|string} path The path of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new function. diff --git a/math.default.js b/math.default.js new file mode 100644 index 000000000..56fc9bca7 --- /dev/null +++ b/math.default.js @@ -0,0 +1,18 @@ +import add from './add'; +import ceil from './ceil'; +import floor from './floor'; +import max from './max'; +import maxBy from './maxBy'; +import mean from './mean'; +import min from './min'; +import minBy from './minBy'; +import round from './round'; +import subtract from './subtract'; +import sum from './sum'; +import sumBy from './sumBy'; + +export default { + add, ceil, floor, max, maxBy, + mean, min, minBy, round, subtract, + sum, sumBy +}; diff --git a/math.js b/math.js index 23272eedf..9b7faa088 100644 --- a/math.js +++ b/math.js @@ -1,17 +1,13 @@ -import add from './math/add'; -import ceil from './math/ceil'; -import floor from './math/floor'; -import max from './math/max'; -import min from './math/min'; -import round from './math/round'; -import sum from './math/sum'; - -export default { - 'add': add, - 'ceil': ceil, - 'floor': floor, - 'max': max, - 'min': min, - 'round': round, - 'sum': sum -}; +export { default as add } from './add'; +export { default as ceil } from './ceil'; +export { default as floor } from './floor'; +export { default as max } from './max'; +export { default as maxBy } from './maxBy'; +export { default as mean } from './mean'; +export { default as min } from './min'; +export { default as minBy } from './minBy'; +export { default as round } from './round'; +export { default as subtract } from './subtract'; +export { default as sum } from './sum'; +export { default as sumBy } from './sumBy'; +export { default as default } from './math.default'; diff --git a/math/add.js b/math/add.js deleted file mode 100644 index c8c851d1c..000000000 --- a/math/add.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Adds two numbers. - * - * @static - * @memberOf _ - * @category Math - * @param {number} augend The first number to add. - * @param {number} addend The second number to add. - * @returns {number} Returns the sum. - * @example - * - * _.add(6, 4); - * // => 10 - */ -function add(augend, addend) { - return (+augend || 0) + (+addend || 0); -} - -export default add; diff --git a/math/max.js b/math/max.js deleted file mode 100644 index 16d05210f..000000000 --- a/math/max.js +++ /dev/null @@ -1,56 +0,0 @@ -import createExtremum from '../internal/createExtremum'; -import gt from '../lang/gt'; - -/** Used as references for `-Infinity` and `Infinity`. */ -var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY; - -/** - * Gets the maximum value of `collection`. If `collection` is empty or falsey - * `-Infinity` is returned. If an iteratee function is provided it's 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). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @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 {*} Returns the maximum value. - * @example - * - * _.max([4, 2, 8, 6]); - * // => 8 - * - * _.max([]); - * // => -Infinity - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } - * ]; - * - * _.max(users, function(chr) { - * return chr.age; - * }); - * // => { 'user': 'fred', 'age': 40 } - * - * // using the `_.property` callback shorthand - * _.max(users, 'age'); - * // => { 'user': 'fred', 'age': 40 } - */ -var max = createExtremum(gt, NEGATIVE_INFINITY); - -export default max; diff --git a/math/min.js b/math/min.js deleted file mode 100644 index 362ba6668..000000000 --- a/math/min.js +++ /dev/null @@ -1,56 +0,0 @@ -import createExtremum from '../internal/createExtremum'; -import lt from '../lang/lt'; - -/** Used as references for `-Infinity` and `Infinity`. */ -var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; - -/** - * Gets the minimum value of `collection`. If `collection` is empty or falsey - * `Infinity` is returned. If an iteratee function is provided it's 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). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @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 {*} Returns the minimum value. - * @example - * - * _.min([4, 2, 8, 6]); - * // => 2 - * - * _.min([]); - * // => Infinity - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } - * ]; - * - * _.min(users, function(chr) { - * return chr.age; - * }); - * // => { 'user': 'barney', 'age': 36 } - * - * // using the `_.property` callback shorthand - * _.min(users, 'age'); - * // => { 'user': 'barney', 'age': 36 } - */ -var min = createExtremum(lt, POSITIVE_INFINITY); - -export default min; diff --git a/math/sum.js b/math/sum.js deleted file mode 100644 index 536ec7c7c..000000000 --- a/math/sum.js +++ /dev/null @@ -1,50 +0,0 @@ -import arraySum from '../internal/arraySum'; -import baseCallback from '../internal/baseCallback'; -import baseSum from '../internal/baseSum'; -import isArray from '../lang/isArray'; -import isIterateeCall from '../internal/isIterateeCall'; -import toIterable from '../internal/toIterable'; - -/** - * Gets the sum of the values in `collection`. - * - * @static - * @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]); - * // => 10 - * - * _.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, iteratee, thisArg) { - if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { - iteratee = undefined; - } - iteratee = baseCallback(iteratee, thisArg, 3); - return iteratee.length == 1 - ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) - : baseSum(collection, iteratee); -} - -export default sum; diff --git a/max.js b/max.js new file mode 100644 index 000000000..0efe10a55 --- /dev/null +++ b/max.js @@ -0,0 +1,28 @@ +import baseExtremum from './internal/baseExtremum'; +import gt from './gt'; +import identity from './identity'; + +/** + * Computes the maximum value of `array`. If `array` is empty or falsey + * `undefined` is returned. + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * _.max([]); + * // => undefined + */ +function max(array) { + return (array && array.length) + ? baseExtremum(array, identity, gt) + : undefined; +} + +export default max; diff --git a/maxBy.js b/maxBy.js new file mode 100644 index 000000000..08b632aa5 --- /dev/null +++ b/maxBy.js @@ -0,0 +1,33 @@ +import baseExtremum from './internal/baseExtremum'; +import baseIteratee from './internal/baseIteratee'; +import gt from './gt'; + +/** + * This method is like `_.max` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * the value is ranked. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {*} Returns the maximum value. + * @example + * + * var objects = [{ 'n': 1 }, { 'n': 2 }]; + * + * _.maxBy(objects, function(o) { return o.a; }); + * // => { 'n': 2 } + * + * // using the `_.property` iteratee shorthand + * _.maxBy(objects, 'n'); + * // => { 'n': 2 } + */ +function maxBy(array, iteratee) { + return (array && array.length) + ? baseExtremum(array, baseIteratee(iteratee), gt) + : undefined; +} + +export default maxBy; diff --git a/mean.js b/mean.js new file mode 100644 index 000000000..4d917c575 --- /dev/null +++ b/mean.js @@ -0,0 +1,20 @@ +import sum from './sum'; + +/** + * Computes the mean of the values in `array`. + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {number} Returns the mean. + * @example + * + * _.mean([4, 2, 8, 6]); + * // => 5 + */ +function mean(array) { + return sum(array) / (array ? array.length : 0); +} + +export default mean; diff --git a/function/memoize.js b/memoize.js similarity index 66% rename from function/memoize.js rename to memoize.js index bb4eed49e..42577daf5 100644 --- a/function/memoize.js +++ b/memoize.js @@ -1,4 +1,4 @@ -import MapCache from '../internal/MapCache'; +import MapCache from './internal/MapCache'; /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -7,14 +7,13 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument - * provided to the memoized function is coerced to a string and used as the - * cache key. The `func` is invoked with the `this` binding of the memoized - * function. + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized 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 [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) - * method interface of `get`, `has`, and `set`. + * method interface of `delete`, `get`, `has`, and `set`. * * @static * @memberOf _ @@ -24,35 +23,27 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * @returns {Function} Returns the new memoizing function. * @example * - * var upperCase = _.memoize(function(string) { - * return string.toUpperCase(); - * }); + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; * - * upperCase('fred'); - * // => 'FRED' + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] * * // modifying the result cache - * upperCase.cache.set('fred', 'BARNEY'); - * upperCase('fred'); - * // => 'BARNEY' + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] * * // replacing `_.memoize.Cache` - * var object = { 'user': 'fred' }; - * var other = { 'user': 'barney' }; - * var identity = _.memoize(_.identity); - * - * identity(object); - * // => { 'user': 'fred' } - * identity(other); - * // => { 'user': 'fred' } - * * _.memoize.Cache = WeakMap; - * var identity = _.memoize(_.identity); - * - * identity(object); - * // => { 'user': 'fred' } - * identity(other); - * // => { 'user': 'barney' } */ function memoize(func, resolver) { if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { diff --git a/merge.js b/merge.js new file mode 100644 index 000000000..31ed9c8cc --- /dev/null +++ b/merge.js @@ -0,0 +1,37 @@ +import baseMerge from './internal/baseMerge'; +import createAssigner from './internal/createAssigner'; + +/** + * Recursively merges own and inherited enumerable properties of source + * objects into the destination object, skipping source properties that resolve + * to `undefined`. Array and plain object properties are merged recursively. + * Other objects and value types are overridden by assignment. Source objects + * are applied from left to right. Subsequent sources overwrite property + * assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var users = { + * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * }; + * + * var ages = { + * 'data': [{ 'age': 36 }, { 'age': 40 }] + * }; + * + * _.merge(users, ages); + * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } + */ +var merge = createAssigner(function(object, source) { + baseMerge(object, source); +}); + +export default merge; diff --git a/mergeWith.js b/mergeWith.js new file mode 100644 index 000000000..d03a955e0 --- /dev/null +++ b/mergeWith.js @@ -0,0 +1,43 @@ +import baseMerge from './internal/baseMerge'; +import createAssigner from './internal/createAssigner'; + +/** + * This method is like `_.merge` except that it accepts `customizer` which + * 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 invoked with seven arguments: + * (objValue, srcValue, key, object, source, stack). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var other = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.mergeWith(object, other, customizer); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } + */ +var mergeWith = createAssigner(function(object, source, customizer) { + baseMerge(object, source, customizer); +}); + +export default mergeWith; diff --git a/utility/method.js b/method.js similarity index 62% rename from utility/method.js rename to method.js index eab75386d..cb951de9c 100644 --- a/utility/method.js +++ b/method.js @@ -1,13 +1,13 @@ -import invokePath from '../internal/invokePath'; -import restParam from '../function/restParam'; +import baseInvoke from './internal/baseInvoke'; +import rest from './rest'; /** - * Creates a function that invokes the method at `path` on a given object. + * Creates a function that invokes the method at `path` of a given object. * Any additional arguments are provided to the invoked method. * * @static * @memberOf _ - * @category Utility + * @category Util * @param {Array|string} path The path of the method to invoke. * @param {...*} [args] The arguments to invoke the method with. * @returns {Function} Returns the new function. @@ -21,12 +21,12 @@ import restParam from '../function/restParam'; * _.map(objects, _.method('a.b.c')); * // => [2, 1] * - * _.invoke(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c'); + * _.invokeMap(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c'); * // => [1, 2] */ -var method = restParam(function(path, args) { +var method = rest(function(path, args) { return function(object) { - return invokePath(object, path, args); + return baseInvoke(object, path, args); }; }); diff --git a/utility/methodOf.js b/methodOf.js similarity index 69% rename from utility/methodOf.js rename to methodOf.js index 72dd94259..dfdfb7cb8 100644 --- a/utility/methodOf.js +++ b/methodOf.js @@ -1,14 +1,14 @@ -import invokePath from '../internal/invokePath'; -import restParam from '../function/restParam'; +import baseInvoke from './internal/baseInvoke'; +import rest from './rest'; /** * The opposite of `_.method`; this method creates a function that invokes - * the method at a given path on `object`. Any additional arguments are + * the method at a given path of `object`. Any additional arguments are * provided to the invoked method. * * @static * @memberOf _ - * @category Utility + * @category Util * @param {Object} object The object to query. * @param {...*} [args] The arguments to invoke the method with. * @returns {Function} Returns the new function. @@ -23,9 +23,9 @@ import restParam from '../function/restParam'; * _.map([['a', '2'], ['c', '0']], _.methodOf(object)); * // => [2, 0] */ -var methodOf = restParam(function(object, args) { +var methodOf = rest(function(object, args) { return function(path) { - return invokePath(object, path, args); + return baseInvoke(object, path, args); }; }); diff --git a/min.js b/min.js new file mode 100644 index 000000000..631fa4473 --- /dev/null +++ b/min.js @@ -0,0 +1,28 @@ +import baseExtremum from './internal/baseExtremum'; +import identity from './identity'; +import lt from './lt'; + +/** + * Computes the minimum value of `array`. If `array` is empty or falsey + * `undefined` is returned. + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * _.min([]); + * // => undefined + */ +function min(array) { + return (array && array.length) + ? baseExtremum(array, identity, lt) + : undefined; +} + +export default min; diff --git a/minBy.js b/minBy.js new file mode 100644 index 000000000..695b573de --- /dev/null +++ b/minBy.js @@ -0,0 +1,33 @@ +import baseExtremum from './internal/baseExtremum'; +import baseIteratee from './internal/baseIteratee'; +import lt from './lt'; + +/** + * This method is like `_.min` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * the value is ranked. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {*} Returns the minimum value. + * @example + * + * var objects = [{ 'n': 1 }, { 'n': 2 }]; + * + * _.minBy(objects, function(o) { return o.a; }); + * // => { 'n': 1 } + * + * // using the `_.property` iteratee shorthand + * _.minBy(objects, 'n'); + * // => { 'n': 1 } + */ +function minBy(array, iteratee) { + return (array && array.length) + ? baseExtremum(array, baseIteratee(iteratee), lt) + : undefined; +} + +export default minBy; diff --git a/mixin.js b/mixin.js new file mode 100644 index 000000000..822d9bde2 --- /dev/null +++ b/mixin.js @@ -0,0 +1,74 @@ +import arrayEach from './internal/arrayEach'; +import arrayPush from './internal/arrayPush'; +import baseFunctions from './internal/baseFunctions'; +import copyArray from './internal/copyArray'; +import isFunction from './isFunction'; +import isObject from './isObject'; +import keys from './keys'; + +/** + * Adds all own enumerable function properties of a source object to the + * 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 to + * avoid conflicts caused by modifying the original. + * + * @static + * @memberOf _ + * @category Util + * @param {Function|Object} [object=lodash] The destination object. + * @param {Object} source The object of functions to add. + * @param {Object} [options] The options object. + * @param {boolean} [options.chain=true] Specify whether the functions added + * are chainable. + * @returns {Function|Object} Returns `object`. + * @example + * + * function vowels(string) { + * return _.filter(string, function(v) { + * return /[aeiou]/i.test(v); + * }); + * } + * + * _.mixin({ 'vowels': vowels }); + * _.vowels('fred'); + * // => ['e'] + * + * _('fred').vowels().value(); + * // => ['e'] + * + * _.mixin({ 'vowels': vowels }, { 'chain': false }); + * _('fred').vowels(); + * // => ['e'] + */ +function mixin(object, source, options) { + var props = keys(source), + methodNames = baseFunctions(source, props); + + var chain = (isObject(options) && 'chain' in options) ? options.chain : true, + isFunc = isFunction(object); + + arrayEach(methodNames, function(methodName) { + var func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), + actions = result.__actions__ = copyArray(this.__actions__); + + actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([this.value()], arguments)); + }; + } + }); + + return object; +} + +export default mixin; diff --git a/function/negate.js b/negate.js similarity index 100% rename from function/negate.js rename to negate.js diff --git a/next.js b/next.js new file mode 100644 index 000000000..5967dbf9d --- /dev/null +++ b/next.js @@ -0,0 +1,34 @@ +import toArray from './toArray'; + +/** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ +function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; +} + +export default wrapperNext; diff --git a/utility/noop.js b/noop.js similarity index 93% rename from utility/noop.js rename to noop.js index 8b697d7bc..b7bed8503 100644 --- a/utility/noop.js +++ b/noop.js @@ -4,7 +4,7 @@ * * @static * @memberOf _ - * @category Utility + * @category Util * @example * * var object = { 'user': 'fred' }; diff --git a/now.js b/now.js new file mode 100644 index 000000000..8480fdf46 --- /dev/null +++ b/now.js @@ -0,0 +1,19 @@ +/** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @type Function + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => logs the number of milliseconds it took for the deferred function to be invoked + */ +var now = Date.now; + +export default now; diff --git a/nthArg.js b/nthArg.js new file mode 100644 index 000000000..996fe2b52 --- /dev/null +++ b/nthArg.js @@ -0,0 +1,25 @@ +import toInteger from './toInteger'; + +/** + * Creates a function that returns its nth argument. + * + * @static + * @memberOf _ + * @category Util + * @param {number} [n=0] The index of the argument to return. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.nthArg(1); + * + * func('a', 'b', 'c'); + * // => 'b' + */ +function nthArg(n) { + n = toInteger(n); + return function() { + return arguments[n]; + }; +} + +export default nthArg; diff --git a/number.default.js b/number.default.js new file mode 100644 index 000000000..98fd81715 --- /dev/null +++ b/number.default.js @@ -0,0 +1,7 @@ +import clamp from './clamp'; +import inRange from './inRange'; +import random from './random'; + +export default { + clamp, inRange, random +}; diff --git a/number.js b/number.js index 005dad038..cfffee737 100644 --- a/number.js +++ b/number.js @@ -1,7 +1,4 @@ -import inRange from './number/inRange'; -import random from './number/random'; - -export default { - 'inRange': inRange, - 'random': random -}; +export { default as clamp } from './clamp'; +export { default as inRange } from './inRange'; +export { default as random } from './random'; +export { default as default } from './number.default'; diff --git a/number/random.js b/number/random.js deleted file mode 100644 index 7ac049bb5..000000000 --- a/number/random.js +++ /dev/null @@ -1,70 +0,0 @@ -import baseRandom from '../internal/baseRandom'; -import isIterateeCall from '../internal/isIterateeCall'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMin = Math.min, - nativeRandom = Math.random; - -/** - * Produces a random number between `min` and `max` (inclusive). If only one - * argument is provided a number between `0` and the given number is returned. - * If `floating` is `true`, or either `min` or `max` are floats, a floating-point - * number is returned instead of an integer. - * - * @static - * @memberOf _ - * @category Number - * @param {number} [min=0] The minimum possible value. - * @param {number} [max=1] The maximum possible value. - * @param {boolean} [floating] Specify returning a floating-point number. - * @returns {number} Returns the random number. - * @example - * - * _.random(0, 5); - * // => an integer between 0 and 5 - * - * _.random(5); - * // => also an integer between 0 and 5 - * - * _.random(5, true); - * // => a floating-point number between 0 and 5 - * - * _.random(1.2, 5.2); - * // => a floating-point number between 1.2 and 5.2 - */ -function random(min, max, floating) { - if (floating && isIterateeCall(min, max, floating)) { - max = floating = undefined; - } - var noMin = min == null, - noMax = max == null; - - if (floating == null) { - if (noMax && typeof min == 'boolean') { - floating = min; - min = 1; - } - else if (typeof max == 'boolean') { - floating = max; - noMax = true; - } - } - if (noMin && noMax) { - max = 1; - noMax = false; - } - min = +min || 0; - if (noMax) { - max = min; - min = 0; - } else { - max = +max || 0; - } - if (floating || min % 1 || max % 1) { - var rand = nativeRandom(); - return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max); - } - return baseRandom(min, max); -} - -export default random; diff --git a/object.default.js b/object.default.js new file mode 100644 index 000000000..fcc640a14 --- /dev/null +++ b/object.default.js @@ -0,0 +1,50 @@ +import assign from './assign'; +import assignIn from './assignIn'; +import assignInWith from './assignInWith'; +import assignWith from './assignWith'; +import create from './create'; +import defaults from './defaults'; +import defaultsDeep from './defaultsDeep'; +import findKey from './findKey'; +import findLastKey from './findLastKey'; +import forIn from './forIn'; +import forInRight from './forInRight'; +import forOwn from './forOwn'; +import forOwnRight from './forOwnRight'; +import functions from './functions'; +import functionsIn from './functionsIn'; +import get from './get'; +import has from './has'; +import hasIn from './hasIn'; +import invert from './invert'; +import invoke from './invoke'; +import keys from './keys'; +import keysIn from './keysIn'; +import mapKeys from './mapKeys'; +import mapValues from './mapValues'; +import merge from './merge'; +import mergeWith from './mergeWith'; +import omit from './omit'; +import omitBy from './omitBy'; +import pick from './pick'; +import pickBy from './pickBy'; +import result from './result'; +import set from './set'; +import setWith from './setWith'; +import toPairs from './toPairs'; +import toPairsIn from './toPairsIn'; +import transform from './transform'; +import unset from './unset'; +import values from './values'; +import valuesIn from './valuesIn'; + +export default { + assign, assignIn, assignInWith, assignWith, create, + defaults, defaultsDeep, findKey, findLastKey, forIn, + forInRight, forOwn, forOwnRight, functions, functionsIn, + get, has, hasIn, invert, invoke, + keys, keysIn, mapKeys, mapValues, merge, + mergeWith, omit, omitBy, pick, pickBy, + result, set, setWith, toPairs, toPairsIn, + transform, unset, values, valuesIn +}; diff --git a/object.js b/object.js index 87dddcc70..a95f299e3 100644 --- a/object.js +++ b/object.js @@ -1,61 +1,40 @@ -import assign from './object/assign'; -import create from './object/create'; -import defaults from './object/defaults'; -import defaultsDeep from './object/defaultsDeep'; -import extend from './object/extend'; -import findKey from './object/findKey'; -import findLastKey from './object/findLastKey'; -import forIn from './object/forIn'; -import forInRight from './object/forInRight'; -import forOwn from './object/forOwn'; -import forOwnRight from './object/forOwnRight'; -import functions from './object/functions'; -import get from './object/get'; -import has from './object/has'; -import invert from './object/invert'; -import keys from './object/keys'; -import keysIn from './object/keysIn'; -import mapKeys from './object/mapKeys'; -import mapValues from './object/mapValues'; -import merge from './object/merge'; -import methods from './object/methods'; -import omit from './object/omit'; -import pairs from './object/pairs'; -import pick from './object/pick'; -import result from './object/result'; -import set from './object/set'; -import transform from './object/transform'; -import values from './object/values'; -import valuesIn from './object/valuesIn'; - -export default { - 'assign': assign, - 'create': create, - 'defaults': defaults, - 'defaultsDeep': defaultsDeep, - 'extend': extend, - 'findKey': findKey, - 'findLastKey': findLastKey, - 'forIn': forIn, - 'forInRight': forInRight, - 'forOwn': forOwn, - 'forOwnRight': forOwnRight, - 'functions': functions, - 'get': get, - 'has': has, - 'invert': invert, - 'keys': keys, - 'keysIn': keysIn, - 'mapKeys': mapKeys, - 'mapValues': mapValues, - 'merge': merge, - 'methods': methods, - 'omit': omit, - 'pairs': pairs, - 'pick': pick, - 'result': result, - 'set': set, - 'transform': transform, - 'values': values, - 'valuesIn': valuesIn -}; +export { default as assign } from './assign'; +export { default as assignIn } from './assignIn'; +export { default as assignInWith } from './assignInWith'; +export { default as assignWith } from './assignWith'; +export { default as create } from './create'; +export { default as defaults } from './defaults'; +export { default as defaultsDeep } from './defaultsDeep'; +export { default as findKey } from './findKey'; +export { default as findLastKey } from './findLastKey'; +export { default as forIn } from './forIn'; +export { default as forInRight } from './forInRight'; +export { default as forOwn } from './forOwn'; +export { default as forOwnRight } from './forOwnRight'; +export { default as functions } from './functions'; +export { default as functionsIn } from './functionsIn'; +export { default as get } from './get'; +export { default as has } from './has'; +export { default as hasIn } from './hasIn'; +export { default as invert } from './invert'; +export { default as invoke } from './invoke'; +export { default as keys } from './keys'; +export { default as keysIn } from './keysIn'; +export { default as mapKeys } from './mapKeys'; +export { default as mapValues } from './mapValues'; +export { default as merge } from './merge'; +export { default as mergeWith } from './mergeWith'; +export { default as omit } from './omit'; +export { default as omitBy } from './omitBy'; +export { default as pick } from './pick'; +export { default as pickBy } from './pickBy'; +export { default as result } from './result'; +export { default as set } from './set'; +export { default as setWith } from './setWith'; +export { default as toPairs } from './toPairs'; +export { default as toPairsIn } from './toPairsIn'; +export { default as transform } from './transform'; +export { default as unset } from './unset'; +export { default as values } from './values'; +export { default as valuesIn } from './valuesIn'; +export { default as default } from './object.default'; diff --git a/object/assign.js b/object/assign.js deleted file mode 100644 index eaaca53da..000000000 --- a/object/assign.js +++ /dev/null @@ -1,43 +0,0 @@ -import assignWith from '../internal/assignWith'; -import baseAssign from '../internal/baseAssign'; -import createAssigner from '../internal/createAssigner'; - -/** - * 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's invoked to produce the assigned values. - * The `customizer` is bound to `thisArg` and invoked with five arguments: - * (objectValue, sourceValue, key, object, source). - * - * **Note:** This method mutates `object` and is based on - * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign). - * - * @static - * @memberOf _ - * @alias extend - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {Object} Returns `object`. - * @example - * - * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' }); - * // => { 'user': 'fred', 'age': 40 } - * - * // using a customizer callback - * var defaults = _.partialRight(_.assign, function(value, other) { - * return _.isUndefined(value) ? other : value; - * }); - * - * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); - * // => { 'user': 'barney', 'age': 36 } - */ -var assign = createAssigner(function(object, source, customizer) { - return customizer - ? assignWith(object, source, customizer) - : baseAssign(object, source); -}); - -export default assign; diff --git a/object/defaults.js b/object/defaults.js deleted file mode 100644 index 70a561dda..000000000 --- a/object/defaults.js +++ /dev/null @@ -1,25 +0,0 @@ -import assign from './assign'; -import assignDefaults from '../internal/assignDefaults'; -import createDefaults from '../internal/createDefaults'; - -/** - * Assigns own enumerable properties of source object(s) to the destination - * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional values of the same property are ignored. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @example - * - * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); - * // => { 'user': 'barney', 'age': 36 } - */ -var defaults = createDefaults(assign, assignDefaults); - -export default defaults; diff --git a/object/extend.js b/object/extend.js deleted file mode 100644 index 89b31da03..000000000 --- a/object/extend.js +++ /dev/null @@ -1,2 +0,0 @@ -import assign from './assign' -export default assign; diff --git a/object/findKey.js b/object/findKey.js deleted file mode 100644 index 2132e3314..000000000 --- a/object/findKey.js +++ /dev/null @@ -1,54 +0,0 @@ -import baseForOwn from '../internal/baseForOwn'; -import createFindKey from '../internal/createFindKey'; - -/** - * 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. - * - * 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {string|undefined} Returns the key of the matched element, else `undefined`. - * @example - * - * var users = { - * 'barney': { 'age': 36, 'active': true }, - * 'fred': { 'age': 40, 'active': false }, - * 'pebbles': { 'age': 1, 'active': true } - * }; - * - * _.findKey(users, function(chr) { - * return chr.age < 40; - * }); - * // => 'barney' (iteration order is not guaranteed) - * - * // using the `_.matches` callback shorthand - * _.findKey(users, { 'age': 1, 'active': true }); - * // => 'pebbles' - * - * // using the `_.matchesProperty` callback shorthand - * _.findKey(users, 'active', false); - * // => 'fred' - * - * // using the `_.property` callback shorthand - * _.findKey(users, 'active'); - * // => 'barney' - */ -var findKey = createFindKey(baseForOwn); - -export default findKey; diff --git a/object/findLastKey.js b/object/findLastKey.js deleted file mode 100644 index d12b2f5ee..000000000 --- a/object/findLastKey.js +++ /dev/null @@ -1,54 +0,0 @@ -import baseForOwnRight from '../internal/baseForOwnRight'; -import createFindKey from '../internal/createFindKey'; - -/** - * This method is like `_.findKey` except that it iterates over elements of - * a collection in the opposite order. - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to search. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {string|undefined} Returns the key of the matched element, else `undefined`. - * @example - * - * var users = { - * 'barney': { 'age': 36, 'active': true }, - * 'fred': { 'age': 40, 'active': false }, - * 'pebbles': { 'age': 1, 'active': true } - * }; - * - * _.findLastKey(users, function(chr) { - * return chr.age < 40; - * }); - * // => returns `pebbles` assuming `_.findKey` returns `barney` - * - * // using the `_.matches` callback shorthand - * _.findLastKey(users, { 'age': 36, 'active': true }); - * // => 'barney' - * - * // using the `_.matchesProperty` callback shorthand - * _.findLastKey(users, 'active', false); - * // => 'fred' - * - * // using the `_.property` callback shorthand - * _.findLastKey(users, 'active'); - * // => 'pebbles' - */ -var findLastKey = createFindKey(baseForOwnRight); - -export default findLastKey; diff --git a/object/functions.js b/object/functions.js deleted file mode 100644 index 4e5ac25e9..000000000 --- a/object/functions.js +++ /dev/null @@ -1,23 +0,0 @@ -import baseFunctions from '../internal/baseFunctions'; -import keysIn from './keysIn'; - -/** - * Creates an array of function property names from all enumerable properties, - * own and inherited, of `object`. - * - * @static - * @memberOf _ - * @alias methods - * @category Object - * @param {Object} object The object to inspect. - * @returns {Array} Returns the new array of property names. - * @example - * - * _.functions(_); - * // => ['after', 'ary', 'assign', ...] - */ -function functions(object) { - return baseFunctions(object, keysIn(object)); -} - -export default functions; diff --git a/object/has.js b/object/has.js deleted file mode 100644 index a4f413c2a..000000000 --- a/object/has.js +++ /dev/null @@ -1,57 +0,0 @@ -import baseGet from '../internal/baseGet'; -import baseSlice from '../internal/baseSlice'; -import isArguments from '../lang/isArguments'; -import isArray from '../lang/isArray'; -import isIndex from '../internal/isIndex'; -import isKey from '../internal/isKey'; -import isLength from '../internal/isLength'; -import last from '../array/last'; -import toPath from '../internal/toPath'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Checks if `path` is a direct property. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @returns {boolean} Returns `true` if `path` is a direct property, else `false`. - * @example - * - * var object = { 'a': { 'b': { 'c': 3 } } }; - * - * _.has(object, 'a'); - * // => true - * - * _.has(object, 'a.b.c'); - * // => true - * - * _.has(object, ['a', 'b', 'c']); - * // => true - */ -function has(object, path) { - if (object == null) { - return false; - } - var result = hasOwnProperty.call(object, path); - if (!result && !isKey(path)) { - path = toPath(path); - object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); - if (object == null) { - return false; - } - path = last(path); - result = hasOwnProperty.call(object, path); - } - return result || (isLength(object.length) && isIndex(path, object.length) && - (isArray(object) || isArguments(object))); -} - -export default has; diff --git a/object/keys.js b/object/keys.js deleted file mode 100644 index 7ef34b37c..000000000 --- a/object/keys.js +++ /dev/null @@ -1,45 +0,0 @@ -import getNative from '../internal/getNative'; -import isArrayLike from '../internal/isArrayLike'; -import isObject from '../lang/isObject'; -import shimKeys from '../internal/shimKeys'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeKeys = getNative(Object, 'keys'); - -/** - * Creates an array of the own enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) - * for more details. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keys(new Foo); - * // => ['a', 'b'] (iteration order is not guaranteed) - * - * _.keys('hi'); - * // => ['0', '1'] - */ -var keys = !nativeKeys ? shimKeys : function(object) { - var Ctor = object == null ? undefined : object.constructor; - if ((typeof Ctor == 'function' && Ctor.prototype === object) || - (typeof object != 'function' && isArrayLike(object))) { - return shimKeys(object); - } - return isObject(object) ? nativeKeys(object) : []; -}; - -export default keys; diff --git a/object/keysIn.js b/object/keysIn.js deleted file mode 100644 index 20b9dd281..000000000 --- a/object/keysIn.js +++ /dev/null @@ -1,64 +0,0 @@ -import isArguments from '../lang/isArguments'; -import isArray from '../lang/isArray'; -import isIndex from '../internal/isIndex'; -import isLength from '../internal/isLength'; -import isObject from '../lang/isObject'; - -/** Used for native method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keysIn(new Foo); - * // => ['a', 'b', 'c'] (iteration order is not guaranteed) - */ -function keysIn(object) { - if (object == null) { - return []; - } - if (!isObject(object)) { - object = Object(object); - } - var length = object.length; - length = (length && isLength(length) && - (isArray(object) || isArguments(object)) && length) || 0; - - var Ctor = object.constructor, - index = -1, - isProto = typeof Ctor == 'function' && Ctor.prototype === object, - result = Array(length), - skipIndexes = length > 0; - - while (++index < length) { - result[index] = (index + ''); - } - for (var key in object) { - if (!(skipIndexes && isIndex(key, length)) && - !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { - result.push(key); - } - } - return result; -} - -export default keysIn; diff --git a/object/mapValues.js b/object/mapValues.js deleted file mode 100644 index 852668b99..000000000 --- a/object/mapValues.js +++ /dev/null @@ -1,46 +0,0 @@ -import createObjectMapper from '../internal/createObjectMapper'; - -/** - * 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: - * (value, key, object). - * - * 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 `iteratee` the created `_.matches` style - * callback returns `true` for elements that have the properties of the given - * object, else `false`. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Object} Returns the new mapped object. - * @example - * - * _.mapValues({ 'a': 1, 'b': 2 }, function(n) { - * return n * 3; - * }); - * // => { 'a': 3, 'b': 6 } - * - * var users = { - * 'fred': { 'user': 'fred', 'age': 40 }, - * 'pebbles': { 'user': 'pebbles', 'age': 1 } - * }; - * - * // using the `_.property` callback shorthand - * _.mapValues(users, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) - */ -var mapValues = createObjectMapper(); - -export default mapValues; diff --git a/object/merge.js b/object/merge.js deleted file mode 100644 index 8f54fbeaf..000000000 --- a/object/merge.js +++ /dev/null @@ -1,54 +0,0 @@ -import baseMerge from '../internal/baseMerge'; -import createAssigner from '../internal/createAssigner'; - -/** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * overwrite property assignments of previous sources. If `customizer` is - * provided it's 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). - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @param {*} [thisArg] The `this` binding of `customizer`. - * @returns {Object} Returns `object`. - * @example - * - * var users = { - * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] - * }; - * - * var ages = { - * 'data': [{ 'age': 36 }, { 'age': 40 }] - * }; - * - * _.merge(users, ages); - * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } - * - * // using a customizer callback - * var object = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var other = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(object, other, function(a, b) { - * if (_.isArray(a)) { - * return a.concat(b); - * } - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } - */ -var merge = createAssigner(baseMerge); - -export default merge; diff --git a/object/methods.js b/object/methods.js deleted file mode 100644 index 265229eb3..000000000 --- a/object/methods.js +++ /dev/null @@ -1,2 +0,0 @@ -import functions from './functions' -export default functions; diff --git a/object/omit.js b/object/omit.js deleted file mode 100644 index f89df57c3..000000000 --- a/object/omit.js +++ /dev/null @@ -1,47 +0,0 @@ -import arrayMap from '../internal/arrayMap'; -import baseDifference from '../internal/baseDifference'; -import baseFlatten from '../internal/baseFlatten'; -import bindCallback from '../internal/bindCallback'; -import keysIn from './keysIn'; -import pickByArray from '../internal/pickByArray'; -import pickByCallback from '../internal/pickByCallback'; -import restParam from '../function/restParam'; - -/** - * The opposite of `_.pick`; this method creates an object composed of the - * own and inherited enumerable properties of `object` that are not omitted. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function invoked per - * iteration or property names to omit, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'user': 'fred', 'age': 40 }; - * - * _.omit(object, 'age'); - * // => { 'user': 'fred' } - * - * _.omit(object, _.isNumber); - * // => { 'user': 'fred' } - */ -var omit = restParam(function(object, props) { - if (object == null) { - return {}; - } - if (typeof props[0] != 'function') { - var props = arrayMap(baseFlatten(props), String); - return pickByArray(object, baseDifference(keysIn(object), props)); - } - var predicate = bindCallback(props[0], props[1], 3); - return pickByCallback(object, function(value, key, object) { - return !predicate(value, key, object); - }); -}); - -export default omit; diff --git a/object/pairs.js b/object/pairs.js deleted file mode 100644 index 8a4caaf54..000000000 --- a/object/pairs.js +++ /dev/null @@ -1,33 +0,0 @@ -import keys from './keys'; -import toObject from '../internal/toObject'; - -/** - * Creates a two dimensional array of the key-value pairs for `object`, - * e.g. `[[key1, value1], [key2, value2]]`. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the new array of key-value pairs. - * @example - * - * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) - */ -function pairs(object) { - object = toObject(object); - - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - var key = props[index]; - result[index] = [key, object[key]]; - } - return result; -} - -export default pairs; diff --git a/object/pick.js b/object/pick.js deleted file mode 100644 index ed4057896..000000000 --- a/object/pick.js +++ /dev/null @@ -1,42 +0,0 @@ -import baseFlatten from '../internal/baseFlatten'; -import bindCallback from '../internal/bindCallback'; -import pickByArray from '../internal/pickByArray'; -import pickByCallback from '../internal/pickByCallback'; -import restParam from '../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's 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). - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The source object. - * @param {Function|...(string|string[])} [predicate] The function invoked per - * iteration or property names to pick, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `predicate`. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'user': 'fred', 'age': 40 }; - * - * _.pick(object, 'user'); - * // => { 'user': 'fred' } - * - * _.pick(object, _.isString); - * // => { 'user': 'fred' } - */ -var pick = restParam(function(object, props) { - if (object == null) { - return {}; - } - return typeof props[0] == 'function' - ? pickByCallback(object, bindCallback(props[0], props[1], 3)) - : pickByArray(object, baseFlatten(props)); -}); - -export default pick; diff --git a/object/set.js b/object/set.js deleted file mode 100644 index fecfe9f46..000000000 --- a/object/set.js +++ /dev/null @@ -1,55 +0,0 @@ -import isIndex from '../internal/isIndex'; -import isKey from '../internal/isKey'; -import isObject from '../lang/isObject'; -import toPath from '../internal/toPath'; - -/** - * Sets the property value of `path` on `object`. If a portion of `path` - * does not exist it's created. - * - * @static - * @memberOf _ - * @category Object - * @param {Object} object The object to augment. - * @param {Array|string} path The path of the property to set. - * @param {*} value The value to set. - * @returns {Object} Returns `object`. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.set(object, 'a[0].b.c', 4); - * console.log(object.a[0].b.c); - * // => 4 - * - * _.set(object, 'x[0].y.z', 5); - * console.log(object.x[0].y.z); - * // => 5 - */ -function set(object, path, value) { - if (object == null) { - return object; - } - var pathKey = (path + ''); - path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path); - - var index = -1, - length = path.length, - lastIndex = length - 1, - nested = object; - - while (nested != null && ++index < length) { - var key = path[index]; - if (isObject(nested)) { - if (index == lastIndex) { - nested[key] = value; - } else if (nested[key] == null) { - nested[key] = isIndex(path[index + 1]) ? [] : {}; - } - } - nested = nested[key]; - } - return object; -} - -export default set; diff --git a/omit.js b/omit.js new file mode 100644 index 000000000..ed341bce8 --- /dev/null +++ b/omit.js @@ -0,0 +1,34 @@ +import arrayMap from './internal/arrayMap'; +import baseDifference from './internal/baseDifference'; +import baseFlatten from './internal/baseFlatten'; +import basePick from './internal/basePick'; +import keysIn from './keysIn'; +import rest from './rest'; + +/** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable properties of `object` that are not omitted. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [props] The property names to omit, specified + * individually or in arrays.. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ +var omit = rest(function(object, props) { + if (object == null) { + return {}; + } + props = arrayMap(baseFlatten(props), String); + return basePick(object, baseDifference(keysIn(object), props)); +}); + +export default omit; diff --git a/omitBy.js b/omitBy.js new file mode 100644 index 000000000..f41111a7a --- /dev/null +++ b/omitBy.js @@ -0,0 +1,29 @@ +import baseIteratee from './internal/baseIteratee'; +import basePickBy from './internal/basePickBy'; + +/** + * The opposite of `_.pickBy`; this method creates an object composed of the + * own and inherited enumerable properties of `object` that `predicate` + * doesn't return truthy for. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ +function omitBy(object, predicate) { + predicate = baseIteratee(predicate); + return basePickBy(object, function(value) { + return !predicate(value); + }); +} + +export default omitBy; diff --git a/function/once.js b/once.js similarity index 77% rename from function/once.js rename to once.js index d09ae01ea..5ef7b63c8 100644 --- a/function/once.js +++ b/once.js @@ -2,8 +2,8 @@ import before from './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 and arguments of the created function. + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. * * @static * @memberOf _ diff --git a/orderBy.js b/orderBy.js new file mode 100644 index 000000000..dd3c2a6d8 --- /dev/null +++ b/orderBy.js @@ -0,0 +1,45 @@ +import baseOrderBy from './internal/baseOrderBy'; +import isArray from './isArray'; + +/** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} [iteratees=[_.identity]] The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 42 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // sort by `user` in ascending order and by `age` in descending order + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] + */ +function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); +} + +export default orderBy; diff --git a/over.js b/over.js new file mode 100644 index 000000000..38502a411 --- /dev/null +++ b/over.js @@ -0,0 +1,22 @@ +import arrayMap from './internal/arrayMap'; +import createOver from './internal/createOver'; + +/** + * Creates a function that invokes `iteratees` with the arguments provided + * to the created function and returns their results. + * + * @static + * @memberOf _ + * @category Util + * @param {...(Function|Function[])} iteratees The iteratees to invoke. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.over(Math.max, Math.min); + * + * func(1, 2, 3, 4); + * // => [4, 1] + */ +var over = createOver(arrayMap); + +export default over; diff --git a/overArgs.js b/overArgs.js new file mode 100644 index 000000000..5929f42b7 --- /dev/null +++ b/overArgs.js @@ -0,0 +1,56 @@ +import apply from './internal/apply'; +import arrayMap from './internal/arrayMap'; +import baseFlatten from './internal/baseFlatten'; +import baseIteratee from './internal/baseIteratee'; +import rest from './rest'; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Creates a function that invokes `func` with arguments transformed by + * corresponding `transforms`. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms] The functions to transform + * arguments, specified individually or in arrays. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, square, doubled); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ +var overArgs = rest(function(func, transforms) { + transforms = arrayMap(baseFlatten(transforms), baseIteratee); + + var funcsLength = transforms.length; + return rest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); +}); + +export default overArgs; diff --git a/overEvery.js b/overEvery.js new file mode 100644 index 000000000..922624d77 --- /dev/null +++ b/overEvery.js @@ -0,0 +1,28 @@ +import arrayEvery from './internal/arrayEvery'; +import createOver from './internal/createOver'; + +/** + * Creates a function that checks if **all** of the `predicates` return + * truthy when invoked with the arguments provided to the created function. + * + * @static + * @memberOf _ + * @category Util + * @param {...(Function|Function[])} predicates The predicates to check. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.overEvery(Boolean, isFinite); + * + * func('1'); + * // => true + * + * func(null); + * // => false + * + * func(NaN); + * // => false + */ +var overEvery = createOver(arrayEvery); + +export default overEvery; diff --git a/overSome.js b/overSome.js new file mode 100644 index 000000000..1e41a8b16 --- /dev/null +++ b/overSome.js @@ -0,0 +1,28 @@ +import arraySome from './internal/arraySome'; +import createOver from './internal/createOver'; + +/** + * Creates a function that checks if **any** of the `predicates` return + * truthy when invoked with the arguments provided to the created function. + * + * @static + * @memberOf _ + * @category Util + * @param {...(Function|Function[])} predicates The predicates to check. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.overSome(Boolean, isFinite); + * + * func('1'); + * // => true + * + * func(null); + * // => true + * + * func(NaN); + * // => false + */ +var overSome = createOver(arraySome); + +export default overSome; diff --git a/package.json b/package.json index 2f3662244..0376f6def 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,16 @@ { "name": "lodash-es", - "version": "3.10.1", - "description": "The modern build of lodash exported as ES modules.", + "version": "4.0.0", + "description": "Lodash exported as ES modules.", "homepage": "https://lodash.com/custom-builds", "license": "MIT", "jsnext:main": "lodash.js", + "main": "lodash.js", "keywords": "es6, modules, stdlib, util", "author": "John-David Dalton (http://allyoucanleet.com/)", "contributors": [ "John-David Dalton (http://allyoucanleet.com/)", - "Benjamin Tan (https://d10.github.io/)", - "Blaine Bublitz (http://www.iceddev.com/)", - "Kit Cambridge (http://kitcambridge.be/)", + "Blaine Bublitz (https://github.com/phated)", "Mathias Bynens (https://mathiasbynens.be/)" ], "bugs": "https://github.com/lodash/lodash-cli/issues", diff --git a/string/pad.js b/pad.js similarity index 59% rename from string/pad.js rename to pad.js index ce8f2707e..887959d2f 100644 --- a/string/pad.js +++ b/pad.js @@ -1,11 +1,11 @@ -import baseToString from '../internal/baseToString'; -import createPadding from '../internal/createPadding'; -import root from '../internal/root'; +import createPadding from './internal/createPadding'; +import stringSize from './internal/stringSize'; +import toInteger from './toInteger'; +import toString from './toString'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil, - nativeFloor = Math.floor, - nativeIsFinite = root.isFinite; + nativeFloor = Math.floor; /** * Pads `string` on the left and right sides if it's shorter than `length`. @@ -30,19 +30,18 @@ var nativeCeil = Math.ceil, * // => 'abc' */ function pad(string, length, chars) { - string = baseToString(string); - length = +length; + string = toString(string); + length = toInteger(length); - var strLength = string.length; - if (strLength >= length || !nativeIsFinite(length)) { + var strLength = stringSize(string); + if (!length || strLength >= length) { return string; } var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); - chars = createPadding('', rightLength, chars); - return chars.slice(0, leftLength) + string + chars; + return createPadding('', leftLength, chars) + string + createPadding('', rightLength, chars); } export default pad; diff --git a/string/padRight.js b/padEnd.js similarity index 59% rename from string/padRight.js rename to padEnd.js index f4d8dfe97..ada5680fe 100644 --- a/string/padRight.js +++ b/padEnd.js @@ -1,4 +1,5 @@ -import createPadDir from '../internal/createPadDir'; +import createPadding from './internal/createPadding'; +import toString from './toString'; /** * Pads `string` on the right side if it's shorter than `length`. Padding @@ -13,15 +14,18 @@ import createPadDir from '../internal/createPadDir'; * @returns {string} Returns the padded string. * @example * - * _.padRight('abc', 6); + * _.padEnd('abc', 6); * // => 'abc ' * - * _.padRight('abc', 6, '_-'); + * _.padEnd('abc', 6, '_-'); * // => 'abc_-_' * - * _.padRight('abc', 3); + * _.padEnd('abc', 3); * // => 'abc' */ -var padRight = createPadDir(true); +function padEnd(string, length, chars) { + string = toString(string); + return string + createPadding(string, length, chars); +} -export default padRight; +export default padEnd; diff --git a/string/padLeft.js b/padStart.js similarity index 58% rename from string/padLeft.js rename to padStart.js index a6c361317..4cf076fa1 100644 --- a/string/padLeft.js +++ b/padStart.js @@ -1,4 +1,5 @@ -import createPadDir from '../internal/createPadDir'; +import createPadding from './internal/createPadding'; +import toString from './toString'; /** * Pads `string` on the left side if it's shorter than `length`. Padding @@ -13,15 +14,18 @@ import createPadDir from '../internal/createPadDir'; * @returns {string} Returns the padded string. * @example * - * _.padLeft('abc', 6); + * _.padStart('abc', 6); * // => ' abc' * - * _.padLeft('abc', 6, '_-'); + * _.padStart('abc', 6, '_-'); * // => '_-_abc' * - * _.padLeft('abc', 3); + * _.padStart('abc', 3); * // => 'abc' */ -var padLeft = createPadDir(); +function padStart(string, length, chars) { + string = toString(string); + return createPadding(string, length, chars) + string; +} -export default padLeft; +export default padStart; diff --git a/string/parseInt.js b/parseInt.js similarity index 69% rename from string/parseInt.js rename to parseInt.js index 1267b9d34..793d8ece4 100644 --- a/string/parseInt.js +++ b/parseInt.js @@ -1,11 +1,13 @@ -import isIterateeCall from '../internal/isIterateeCall'; -import root from '../internal/root'; -import trim from './trim'; +import root from './internal/root'; +import toString from './toString'; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; /** Used to detect hexadecimal string values. */ -var reHasHexPrefix = /^0[xX]/; +var reHasHexPrefix = /^0x/i; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeParseInt = root.parseInt; /** @@ -21,7 +23,7 @@ var nativeParseInt = root.parseInt; * @category String * @param {string} string The string to convert. * @param {number} [radix] The radix to interpret `value` by. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {number} Returns the converted integer. * @example * @@ -32,15 +34,14 @@ var nativeParseInt = root.parseInt; * // => [6, 8, 10] */ function parseInt(string, radix, guard) { - // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. // Chrome fails to trim leading whitespace characters. // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. - if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + if (guard || radix == null) { radix = 0; } else if (radix) { radix = +radix; } - string = trim(string); + string = toString(string).replace(reTrim, ''); return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); } diff --git a/function/partial.js b/partial.js similarity index 72% rename from function/partial.js rename to partial.js index 4cbdb839a..a07c855f2 100644 --- a/function/partial.js +++ b/partial.js @@ -1,4 +1,6 @@ -import createPartial from '../internal/createPartial'; +import createWrapper from './internal/createWrapper'; +import replaceHolders from './internal/replaceHolders'; +import rest from './rest'; /** Used to compose bitmasks for wrapper metadata. */ var PARTIAL_FLAG = 32; @@ -11,7 +13,7 @@ var PARTIAL_FLAG = 32; * The `_.partial.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * - * **Note:** This method does not set the "length" property of partially + * **Note:** This method doesn't set the "length" property of partially * applied functions. * * @static @@ -35,9 +37,9 @@ var PARTIAL_FLAG = 32; * greetFred('hi'); * // => 'hi fred' */ -var partial = createPartial(PARTIAL_FLAG); - -// Assign default placeholders. -partial.placeholder = {}; +var partial = rest(function(func, partials) { + var holders = replaceHolders(partials, partial.placeholder); + return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders); +}); export default partial; diff --git a/function/partialRight.js b/partialRight.js similarity index 70% rename from function/partialRight.js rename to partialRight.js index 496c46ef9..1fd853b7a 100644 --- a/function/partialRight.js +++ b/partialRight.js @@ -1,4 +1,6 @@ -import createPartial from '../internal/createPartial'; +import createWrapper from './internal/createWrapper'; +import replaceHolders from './internal/replaceHolders'; +import rest from './rest'; /** Used to compose bitmasks for wrapper metadata. */ var PARTIAL_RIGHT_FLAG = 64; @@ -10,7 +12,7 @@ var PARTIAL_RIGHT_FLAG = 64; * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * - * **Note:** This method does not set the "length" property of partially + * **Note:** This method doesn't set the "length" property of partially * applied functions. * * @static @@ -34,9 +36,9 @@ var PARTIAL_RIGHT_FLAG = 64; * sayHelloTo('fred'); * // => 'hello fred' */ -var partialRight = createPartial(PARTIAL_RIGHT_FLAG); - -// Assign default placeholders. -partialRight.placeholder = {}; +var partialRight = rest(function(func, partials) { + var holders = replaceHolders(partials, partialRight.placeholder); + return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders); +}); export default partialRight; diff --git a/partition.js b/partition.js new file mode 100644 index 000000000..732de6144 --- /dev/null +++ b/partition.js @@ -0,0 +1,42 @@ +import createAggregator from './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 invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // using the `_.matches` iteratee shorthand + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // using the `_.property` iteratee shorthand + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ +var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); +}, function() { return [[], []]; }); + +export default partition; diff --git a/pick.js b/pick.js new file mode 100644 index 000000000..f3b83631d --- /dev/null +++ b/pick.js @@ -0,0 +1,26 @@ +import baseFlatten from './internal/baseFlatten'; +import basePick from './internal/basePick'; +import rest from './rest'; + +/** + * Creates an object composed of the picked `object` properties. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [props] The property names to pick, specified + * individually or in arrays. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ +var pick = rest(function(object, props) { + return object == null ? {} : basePick(object, baseFlatten(props)); +}); + +export default pick; diff --git a/pickBy.js b/pickBy.js new file mode 100644 index 000000000..6e8202fe6 --- /dev/null +++ b/pickBy.js @@ -0,0 +1,25 @@ +import baseIteratee from './internal/baseIteratee'; +import basePickBy from './internal/basePickBy'; + +/** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ +function pickBy(object, predicate) { + return object == null ? {} : basePickBy(object, baseIteratee(predicate)); +} + +export default pickBy; diff --git a/chain/wrapperPlant.js b/plant.js similarity index 64% rename from chain/wrapperPlant.js rename to plant.js index d06874670..4adaedcac 100644 --- a/chain/wrapperPlant.js +++ b/plant.js @@ -1,24 +1,24 @@ -import baseLodash from '../internal/baseLodash'; -import wrapperClone from '../internal/wrapperClone'; +import baseLodash from './internal/baseLodash'; +import wrapperClone from './internal/wrapperClone'; /** * Creates a clone of the chained sequence planting `value` as the wrapped value. * * @name plant * @memberOf _ - * @category Chain + * @category Seq + * @param {*} value The value to plant. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * - * var array = [1, 2]; - * var wrapped = _(array).map(function(value) { - * return Math.pow(value, 2); - * }); + * function square(n) { + * return n * n; + * } * - * var other = [3, 4]; - * var otherWrapped = wrapped.plant(other); + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); * - * otherWrapped.value(); + * other.value(); * // => [9, 16] * * wrapped.value(); @@ -30,6 +30,8 @@ function wrapperPlant(value) { while (parent instanceof baseLodash) { var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; if (result) { previous.__wrapped__ = clone; } else { diff --git a/utility/property.js b/property.js similarity index 58% rename from utility/property.js rename to property.js index 8ed39c41a..534035f60 100644 --- a/utility/property.js +++ b/property.js @@ -1,14 +1,13 @@ -import baseProperty from '../internal/baseProperty'; -import basePropertyDeep from '../internal/basePropertyDeep'; -import isKey from '../internal/isKey'; +import baseProperty from './internal/baseProperty'; +import basePropertyDeep from './internal/basePropertyDeep'; +import isKey from './internal/isKey'; /** - * Creates a function that returns the property value at `path` on a - * given object. + * Creates a function that returns the value at `path` of a given object. * * @static * @memberOf _ - * @category Utility + * @category Util * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new function. * @example @@ -21,7 +20,7 @@ import isKey from '../internal/isKey'; * _.map(objects, _.property('a.b.c')); * // => [2, 1] * - * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); + * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); * // => [1, 2] */ function property(path) { diff --git a/utility/propertyOf.js b/propertyOf.js similarity index 72% rename from utility/propertyOf.js rename to propertyOf.js index cdd8b2a5d..9e4d9349e 100644 --- a/utility/propertyOf.js +++ b/propertyOf.js @@ -1,13 +1,12 @@ -import baseGet from '../internal/baseGet'; -import toPath from '../internal/toPath'; +import baseGet from './internal/baseGet'; /** * The opposite of `_.property`; this method creates a function that returns - * the property value at a given path on `object`. + * the value at a given path of `object`. * * @static * @memberOf _ - * @category Utility + * @category Util * @param {Object} object The object to query. * @returns {Function} Returns the new function. * @example @@ -23,7 +22,7 @@ import toPath from '../internal/toPath'; */ function propertyOf(object) { return function(path) { - return baseGet(object, toPath(path), (path + '')); + return object == null ? undefined : baseGet(object, path); }; } diff --git a/pull.js b/pull.js new file mode 100644 index 000000000..7cf423453 --- /dev/null +++ b/pull.js @@ -0,0 +1,27 @@ +import pullAll from './pullAll'; +import rest from './rest'; + +/** + * Removes all provided values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3, 1, 2, 3]; + * + * _.pull(array, 2, 3); + * console.log(array); + * // => [1, 1] + */ +var pull = rest(pullAll); + +export default pull; diff --git a/pullAll.js b/pullAll.js new file mode 100644 index 000000000..d1e2bbba9 --- /dev/null +++ b/pullAll.js @@ -0,0 +1,28 @@ +import basePullAll from './internal/basePullAll'; + +/** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3, 1, 2, 3]; + * + * _.pull(array, [2, 3]); + * console.log(array); + * // => [1, 1] + */ +function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; +} + +export default pullAll; diff --git a/pullAllBy.js b/pullAllBy.js new file mode 100644 index 000000000..e9325f47d --- /dev/null +++ b/pullAllBy.js @@ -0,0 +1,32 @@ +import baseIteratee from './internal/baseIteratee'; +import basePullAllBy from './internal/basePullAllBy'; + +/** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to to generate the criterion + * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ +function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAllBy(array, values, baseIteratee(iteratee)) + : array; +} + +export default pullAllBy; diff --git a/pullAt.js b/pullAt.js new file mode 100644 index 000000000..c99e08049 --- /dev/null +++ b/pullAt.js @@ -0,0 +1,40 @@ +import arrayMap from './internal/arrayMap'; +import baseAt from './internal/baseAt'; +import baseFlatten from './internal/baseFlatten'; +import basePullAt from './internal/basePullAt'; +import compareAscending from './internal/compareAscending'; +import rest from './rest'; + +/** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove, + * specified individually or in arrays. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [5, 10, 15, 20]; + * var evens = _.pullAt(array, 1, 3); + * + * console.log(array); + * // => [5, 15] + * + * console.log(evens); + * // => [10, 20] + */ +var pullAt = rest(function(array, indexes) { + indexes = arrayMap(baseFlatten(indexes), String); + + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(compareAscending)); + return result; +}); + +export default pullAt; diff --git a/random.js b/random.js new file mode 100644 index 000000000..5f23877c5 --- /dev/null +++ b/random.js @@ -0,0 +1,81 @@ +import baseRandom from './internal/baseRandom'; +import isIterateeCall from './internal/isIterateeCall'; +import toNumber from './toNumber'; + +/** Built-in method references without a dependency on `root`. */ +var freeParseFloat = parseFloat; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min, + nativeRandom = Math.random; + +/** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are floats, + * a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ +function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toNumber(lower) || 0; + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toNumber(upper) || 0; + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); +} + +export default random; diff --git a/range.js b/range.js new file mode 100644 index 000000000..a2b349943 --- /dev/null +++ b/range.js @@ -0,0 +1,45 @@ +import createRange from './internal/createRange'; + +/** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to, but not including, `end`. A step of `-1` is used if a negative + * `start` is specified without an `end` or `step`. If `end` is not specified + * it's set to `start` with `start` then set to `0`. If `end` is less than + * `start` a zero-length range is created unless a negative `step` is specified. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @category Util + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the new array of numbers. + * @example + * + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(-4); + * // => [0, -1, -2, -3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ +var range = createRange(); + +export default range; diff --git a/rangeRight.js b/rangeRight.js new file mode 100644 index 000000000..fc3f7d511 --- /dev/null +++ b/rangeRight.js @@ -0,0 +1,39 @@ +import createRange from './internal/createRange'; + +/** + * This method is like `_.range` except that it populates values in + * descending order. + * + * @static + * @memberOf _ + * @category Util + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the new array of numbers. + * @example + * + * _.rangeRight(4); + * // => [3, 2, 1, 0] + * + * _.rangeRight(-4); + * // => [-3, -2, -1, 0] + * + * _.rangeRight(1, 5); + * // => [4, 3, 2, 1] + * + * _.rangeRight(0, 20, 5); + * // => [15, 10, 5, 0] + * + * _.rangeRight(0, -4, -1); + * // => [-3, -2, -1, 0] + * + * _.rangeRight(1, 4, 0); + * // => [1, 1, 1] + * + * _.rangeRight(0); + * // => [] + */ +var rangeRight = createRange(true); + +export default rangeRight; diff --git a/function/rearg.js b/rearg.js similarity index 70% rename from function/rearg.js rename to rearg.js index f72d0c20e..ea11ab4f5 100644 --- a/function/rearg.js +++ b/rearg.js @@ -1,6 +1,6 @@ -import baseFlatten from '../internal/baseFlatten'; -import createWrapper from '../internal/createWrapper'; -import restParam from './restParam'; +import baseFlatten from './internal/baseFlatten'; +import createWrapper from './internal/createWrapper'; +import rest from './rest'; /** Used to compose bitmasks for wrapper metadata. */ var REARG_FLAG = 256; @@ -16,7 +16,7 @@ var REARG_FLAG = 256; * @category Function * @param {Function} func The function to rearrange arguments for. * @param {...(number|number[])} indexes The arranged argument indexes, - * specified as individual indexes or arrays of indexes. + * specified individually or in arrays. * @returns {Function} Returns the new function. * @example * @@ -26,14 +26,8 @@ var REARG_FLAG = 256; * * rearged('b', 'c', 'a') * // => ['a', 'b', 'c'] - * - * var map = _.rearg(_.map, [1, 0]); - * map(function(n) { - * return n * 3; - * }, [1, 2, 3]); - * // => [3, 6, 9] */ -var rearg = restParam(function(func, indexes) { +var rearg = rest(function(func, indexes) { return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); }); diff --git a/reduce.js b/reduce.js new file mode 100644 index 000000000..e0acf968e --- /dev/null +++ b/reduce.js @@ -0,0 +1,49 @@ +import arrayReduce from './internal/arrayReduce'; +import baseEach from './internal/baseEach'; +import baseIteratee from './internal/baseIteratee'; +import baseReduce from './internal/baseReduce'; +import isArray from './isArray'; + +/** + * 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 invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ +function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initFromCollection = arguments.length < 3; + + return func(collection, baseIteratee(iteratee, 4), accumulator, initFromCollection, baseEach); +} + +export default reduce; diff --git a/reduceRight.js b/reduceRight.js new file mode 100644 index 000000000..3a79f1770 --- /dev/null +++ b/reduceRight.js @@ -0,0 +1,34 @@ +import arrayReduceRight from './internal/arrayReduceRight'; +import baseEachRight from './internal/baseEachRight'; +import baseIteratee from './internal/baseIteratee'; +import baseReduce from './internal/baseReduce'; +import isArray from './isArray'; + +/** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ +function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initFromCollection = arguments.length < 3; + + return func(collection, baseIteratee(iteratee, 4), accumulator, initFromCollection, baseEachRight); +} + +export default reduceRight; diff --git a/reject.js b/reject.js new file mode 100644 index 000000000..8651c1312 --- /dev/null +++ b/reject.js @@ -0,0 +1,46 @@ +import arrayFilter from './internal/arrayFilter'; +import baseFilter from './internal/baseFilter'; +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; + +/** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // using the `_.matches` iteratee shorthand + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // using the `_.property` iteratee shorthand + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ +function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = baseIteratee(predicate, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); +} + +export default reject; diff --git a/array/remove.js b/remove.js similarity index 53% rename from array/remove.js rename to remove.js index 3a03a931c..ffa05fbf5 100644 --- a/array/remove.js +++ b/remove.js @@ -1,21 +1,10 @@ -import baseCallback from '../internal/baseCallback'; -import basePullAt from '../internal/basePullAt'; +import baseIteratee from './internal/baseIteratee'; +import basePullAt from './internal/basePullAt'; /** * 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). - * - * If a property name is provided for `predicate` 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 - * callback returns `true` for elements that have the properties of the given - * object, else `false`. + * and returns an array of the removed elements. The predicate is invoked with + * three arguments: (value, index, array). * * **Note:** Unlike `_.filter`, this method mutates `array`. * @@ -23,9 +12,7 @@ import basePullAt from '../internal/basePullAt'; * @memberOf _ * @category Array * @param {Array} array The array to modify. - * @param {Function|Object|string} [predicate=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `predicate`. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. * @returns {Array} Returns the new array of removed elements. * @example * @@ -40,7 +27,7 @@ import basePullAt from '../internal/basePullAt'; * console.log(evens); * // => [2, 4] */ -function remove(array, predicate, thisArg) { +function remove(array, predicate) { var result = []; if (!(array && array.length)) { return result; @@ -49,7 +36,7 @@ function remove(array, predicate, thisArg) { indexes = [], length = array.length; - predicate = baseCallback(predicate, thisArg, 3); + predicate = baseIteratee(predicate, 3); while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { diff --git a/string/repeat.js b/repeat.js similarity index 67% rename from string/repeat.js rename to repeat.js index 7be5b0400..033e79e9c 100644 --- a/string/repeat.js +++ b/repeat.js @@ -1,9 +1,11 @@ -import baseToString from '../internal/baseToString'; -import root from '../internal/root'; +import toInteger from './toInteger'; +import toString from './toString'; -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeFloor = Math.floor, - nativeIsFinite = root.isFinite; +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeFloor = Math.floor; /** * Repeats the given string `n` times. @@ -26,10 +28,11 @@ var nativeFloor = Math.floor, * // => '' */ function repeat(string, n) { + string = toString(string); + n = toInteger(n); + var result = ''; - string = baseToString(string); - n = +n; - if (n < 1 || !string || !nativeIsFinite(n)) { + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { return result; } // Leverage the exponentiation by squaring algorithm for a faster repeat. diff --git a/replace.js b/replace.js new file mode 100644 index 000000000..5db1f2026 --- /dev/null +++ b/replace.js @@ -0,0 +1,27 @@ +import toString from './toString'; + +/** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ +function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); +} + +export default replace; diff --git a/function/restParam.js b/rest.js similarity index 64% rename from function/restParam.js rename to rest.js index d0f5e4da3..6f8ec16e4 100644 --- a/function/restParam.js +++ b/rest.js @@ -1,14 +1,17 @@ +import apply from './internal/apply'; +import toInteger from './toInteger'; + /** 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. */ +/* Built-in 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/Web/JavaScript/Reference/Functions/rest_parameters). + * **Note:** This method is based on the [rest parameter](https://mdn.io/rest_parameters). * * @static * @memberOf _ @@ -18,7 +21,7 @@ var nativeMax = Math.max; * @returns {Function} Returns the new function. * @example * - * var say = _.restParam(function(what, names) { + * var say = _.rest(function(what, names) { * return what + ' ' + _.initial(names).join(', ') + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); * }); @@ -26,33 +29,33 @@ var nativeMax = Math.max; * say('hello', 'fred', 'barney', 'pebbles'); * // => 'hello fred, barney, & pebbles' */ -function restParam(func, start) { +function rest(func, start) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0); + start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0); return function() { var args = arguments, index = -1, length = nativeMax(args.length - start, 0), - rest = Array(length); + array = Array(length); while (++index < length) { - rest[index] = args[start + index]; + array[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); + case 0: return func.call(this, array); + case 1: return func.call(this, args[0], array); + case 2: return func.call(this, args[0], args[1], array); } var otherArgs = Array(start + 1); index = -1; while (++index < start) { otherArgs[index] = args[index]; } - otherArgs[start] = rest; - return func.apply(this, otherArgs); + otherArgs[start] = array; + return apply(func, this, otherArgs); }; } -export default restParam; +export default rest; diff --git a/object/result.js b/result.js similarity index 55% rename from object/result.js rename to result.js index 71cc4b556..c5652cb80 100644 --- a/object/result.js +++ b/result.js @@ -1,9 +1,8 @@ -import baseGet from '../internal/baseGet'; -import baseSlice from '../internal/baseSlice'; -import isFunction from '../lang/isFunction'; -import isKey from '../internal/isKey'; -import last from '../array/last'; -import toPath from '../internal/toPath'; +import baseToPath from './internal/baseToPath'; +import get from './get'; +import isFunction from './isFunction'; +import isKey from './internal/isKey'; +import parent from './internal/parent'; /** * This method is like `_.get` except that if the resolved value is a function @@ -27,21 +26,22 @@ import toPath from '../internal/toPath'; * _.result(object, 'a[0].b.c2'); * // => 4 * - * _.result(object, 'a.b.c', 'default'); + * _.result(object, 'a[0].b.c3', 'default'); * // => 'default' * - * _.result(object, 'a.b.c', _.constant('default')); + * _.result(object, 'a[0].b.c3', _.constant('default')); * // => 'default' */ function result(object, path, defaultValue) { - var result = object == null ? undefined : object[path]; + if (!isKey(path, object)) { + path = baseToPath(path); + var result = get(object, path); + object = parent(object, path); + } else { + result = object == null ? undefined : object[path]; + } if (result === undefined) { - if (object != null && !isKey(path, object)) { - path = toPath(path); - object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); - result = object == null ? undefined : object[last(path)]; - } - result = result === undefined ? defaultValue : result; + result = defaultValue; } return isFunction(result) ? result.call(object) : result; } diff --git a/reverse.js b/reverse.js new file mode 100644 index 000000000..c482b5e22 --- /dev/null +++ b/reverse.js @@ -0,0 +1,31 @@ +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeReverse = arrayProto.reverse; + +/** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @memberOf _ + * @category Array + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ +function reverse(array) { + return array ? nativeReverse.call(array) : array; +} + +export default reverse; diff --git a/math/round.js b/round.js similarity index 70% rename from math/round.js rename to round.js index 9b2728893..ccfd20bee 100644 --- a/math/round.js +++ b/round.js @@ -1,12 +1,12 @@ -import createRound from '../internal/createRound'; +import createRound from './internal/createRound'; /** - * Calculates `n` rounded to `precision`. + * Computes `number` rounded to `precision`. * * @static * @memberOf _ * @category Math - * @param {number} n The number to round. + * @param {number} number The number to round. * @param {number} [precision=0] The precision to round to. * @returns {number} Returns the rounded number. * @example diff --git a/sample.js b/sample.js new file mode 100644 index 000000000..d1add77d0 --- /dev/null +++ b/sample.js @@ -0,0 +1,25 @@ +import baseRandom from './internal/baseRandom'; +import isArrayLike from './isArrayLike'; +import values from './values'; + +/** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ +function sample(collection) { + var array = isArrayLike(collection) ? collection : values(collection), + length = array.length; + + return length > 0 ? array[baseRandom(0, length - 1)] : undefined; +} + +export default sample; diff --git a/sampleSize.js b/sampleSize.js new file mode 100644 index 000000000..cdcfb322c --- /dev/null +++ b/sampleSize.js @@ -0,0 +1,38 @@ +import baseClamp from './internal/baseClamp'; +import baseRandom from './internal/baseRandom'; +import toArray from './toArray'; +import toInteger from './toInteger'; + +/** + * Gets `n` random elements from `collection`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=0] The number of elements to sample. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3, 4], 2); + * // => [3, 1] + */ +function sampleSize(collection, n) { + var index = -1, + result = toArray(collection), + length = result.length, + lastIndex = length - 1; + + n = baseClamp(toInteger(n), 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), + value = result[rand]; + + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; +} + +export default sampleSize; diff --git a/seq.default.js b/seq.default.js new file mode 100644 index 000000000..811dc0724 --- /dev/null +++ b/seq.default.js @@ -0,0 +1,21 @@ +import at from './wrapperAt'; +import chain from './chain'; +import commit from './commit'; +import flatMap from './wrapperFlatMap'; +import lodash from './wrapperLodash'; +import next from './next'; +import plant from './plant'; +import reverse from './wrapperReverse'; +import tap from './tap'; +import thru from './thru'; +import toIterator from './toIterator'; +import toJSON from './toJSON'; +import value from './wrapperValue'; +import valueOf from './valueOf'; +import wrapperChain from './wrapperChain'; + +export default { + at, chain, commit, flatMap, lodash, + next, plant, reverse, tap, thru, + toIterator, toJSON, value, valueOf, wrapperChain +}; diff --git a/seq.js b/seq.js new file mode 100644 index 000000000..9dfa5d89f --- /dev/null +++ b/seq.js @@ -0,0 +1,16 @@ +export { default as at } from './wrapperAt'; +export { default as chain } from './chain'; +export { default as commit } from './commit'; +export { default as flatMap } from './wrapperFlatMap'; +export { default as lodash } from './wrapperLodash'; +export { default as next } from './next'; +export { default as plant } from './plant'; +export { default as reverse } from './wrapperReverse'; +export { default as tap } from './tap'; +export { default as thru } from './thru'; +export { default as toIterator } from './toIterator'; +export { default as toJSON } from './toJSON'; +export { default as value } from './wrapperValue'; +export { default as valueOf } from './valueOf'; +export { default as wrapperChain } from './wrapperChain'; +export { default as default } from './seq.default'; diff --git a/set.js b/set.js new file mode 100644 index 000000000..eeab21b96 --- /dev/null +++ b/set.js @@ -0,0 +1,32 @@ +import baseSet from './internal/baseSet'; + +/** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, 'x[0].y.z', 5); + * console.log(object.x[0].y.z); + * // => 5 + */ +function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); +} + +export default set; diff --git a/setWith.js b/setWith.js new file mode 100644 index 000000000..2950f5860 --- /dev/null +++ b/setWith.js @@ -0,0 +1,27 @@ +import baseSet from './internal/baseSet'; + +/** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * _.setWith({ '0': { 'length': 2 } }, '[0][1][2]', 3, Object); + * // => { '0': { '1': { '2': 3 }, 'length': 2 } } + */ +function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); +} + +export default setWith; diff --git a/collection/shuffle.js b/shuffle.js similarity index 59% rename from collection/shuffle.js rename to shuffle.js index 4ec9ab344..acad96c5a 100644 --- a/collection/shuffle.js +++ b/shuffle.js @@ -1,7 +1,7 @@ -import sample from './sample'; +import sampleSize from './sampleSize'; -/** Used as references for `-Infinity` and `Infinity`. */ -var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295; /** * Creates an array of shuffled values, using a version of the @@ -10,7 +10,7 @@ var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; * @static * @memberOf _ * @category Collection - * @param {Array|Object|string} collection The collection to shuffle. + * @param {Array|Object} collection The collection to shuffle. * @returns {Array} Returns the new shuffled array. * @example * @@ -18,7 +18,7 @@ var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; * // => [4, 1, 3, 2] */ function shuffle(collection) { - return sample(collection, POSITIVE_INFINITY); + return sampleSize(collection, MAX_ARRAY_LENGTH); } export default shuffle; diff --git a/size.js b/size.js new file mode 100644 index 000000000..57cc21aac --- /dev/null +++ b/size.js @@ -0,0 +1,37 @@ +import isArrayLike from './isArrayLike'; +import isString from './isString'; +import keys from './keys'; +import stringSize from './internal/stringSize'; + +/** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable properties for objects. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ +function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + var result = collection.length; + return (result && isString(collection)) ? stringSize(collection) : result; + } + return keys(collection).length; +} + +export default size; diff --git a/array/slice.js b/slice.js similarity index 61% rename from array/slice.js rename to slice.js index 0fe0b64e9..bec70cff2 100644 --- a/array/slice.js +++ b/slice.js @@ -1,11 +1,12 @@ -import baseSlice from '../internal/baseSlice'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseSlice from './internal/baseSlice'; +import isIterateeCall from './internal/isIterateeCall'; +import toInteger from './toInteger'; /** * Creates a slice of `array` from `start` up to, but not including, `end`. * - * **Note:** This method is used instead of `Array#slice` to support node - * lists in IE < 9 and to ensure dense arrays are returned. + * **Note:** This method is used instead of [`Array#slice`](https://mdn.io/Array/slice) + * to ensure dense arrays are returned. * * @static * @memberOf _ @@ -24,6 +25,10 @@ function slice(array, start, end) { start = 0; end = length; } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } return baseSlice(array, start, end); } diff --git a/string/snakeCase.js b/snakeCase.js similarity index 90% rename from string/snakeCase.js rename to snakeCase.js index 3dc9a0b3e..8261f3387 100644 --- a/string/snakeCase.js +++ b/snakeCase.js @@ -1,4 +1,4 @@ -import createCompounder from '../internal/createCompounder'; +import createCompounder from './internal/createCompounder'; /** * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case). diff --git a/some.js b/some.js new file mode 100644 index 000000000..816faef96 --- /dev/null +++ b/some.js @@ -0,0 +1,49 @@ +import arraySome from './internal/arraySome'; +import baseIteratee from './internal/baseIteratee'; +import baseSome from './internal/baseSome'; +import isArray from './isArray'; +import isIterateeCall from './internal/isIterateeCall'; + +/** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // using the `_.matches` iteratee shorthand + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // using the `_.matchesProperty` iteratee shorthand + * _.some(users, ['active', false]); + * // => true + * + * // using the `_.property` iteratee shorthand + * _.some(users, 'active'); + * // => true + */ +function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, baseIteratee(predicate, 3)); +} + +export default some; diff --git a/sortBy.js b/sortBy.js new file mode 100644 index 000000000..cb28447f9 --- /dev/null +++ b/sortBy.js @@ -0,0 +1,52 @@ +import baseFlatten from './internal/baseFlatten'; +import baseOrderBy from './internal/baseOrderBy'; +import isIterateeCall from './internal/isIterateeCall'; +import rest from './rest'; + +/** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection through each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[]|Object|Object[]|string|string[])} [iteratees=[_.identity]] + * The iteratees to sort by, specified individually or in arrays. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 42 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, function(o) { return o.user; }); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]] + * + * _.sortBy(users, 'user', function(o) { + * return Math.floor(o.age / 10); + * }); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]] + */ +var sortBy = rest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees.length = 1; + } + return baseOrderBy(collection, baseFlatten(iteratees), []); +}); + +export default sortBy; diff --git a/sortedIndex.js b/sortedIndex.js new file mode 100644 index 000000000..4665e01da --- /dev/null +++ b/sortedIndex.js @@ -0,0 +1,25 @@ +import baseSortedIndex from './internal/baseSortedIndex'; + +/** + * Uses a binary search to determine the lowest index at which `value` should + * be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + * + * _.sortedIndex([4, 5], 4); + * // => 0 + */ +function sortedIndex(array, value) { + return baseSortedIndex(array, value); +} + +export default sortedIndex; diff --git a/sortedIndexBy.js b/sortedIndexBy.js new file mode 100644 index 000000000..9dec783e6 --- /dev/null +++ b/sortedIndexBy.js @@ -0,0 +1,31 @@ +import baseIteratee from './internal/baseIteratee'; +import baseSortedIndexBy from './internal/baseSortedIndexBy'; + +/** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @example + * + * var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 }; + * + * _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict)); + * // => 1 + * + * // using the `_.property` iteratee shorthand + * _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x'); + * // => 0 + */ +function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, baseIteratee(iteratee)); +} + +export default sortedIndexBy; diff --git a/sortedIndexOf.js b/sortedIndexOf.js new file mode 100644 index 000000000..6c24cedfa --- /dev/null +++ b/sortedIndexOf.js @@ -0,0 +1,30 @@ +import baseSortedIndex from './internal/baseSortedIndex'; +import eq from './eq'; + +/** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([1, 1, 2, 2], 2); + * // => 2 + */ +function sortedIndexOf(array, value) { + var length = array ? array.length : 0; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; +} + +export default sortedIndexOf; diff --git a/array/sortedLastIndex.js b/sortedLastIndex.js similarity index 55% rename from array/sortedLastIndex.js rename to sortedLastIndex.js index f817aa5e1..fed0beb48 100644 --- a/array/sortedLastIndex.js +++ b/sortedLastIndex.js @@ -1,4 +1,4 @@ -import createSortedIndex from '../internal/createSortedIndex'; +import baseSortedIndex from './internal/baseSortedIndex'; /** * This method is like `_.sortedIndex` except that it returns the highest @@ -10,16 +10,14 @@ import createSortedIndex from '../internal/createSortedIndex'; * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. - * @param {Function|Object|string} [iteratee=_.identity] The function invoked - * per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. + * @returns {number} Returns the index at which `value` should be inserted into `array`. * @example * - * _.sortedLastIndex([4, 4, 5, 5], 5); - * // => 4 + * _.sortedLastIndex([4, 5], 4); + * // => 1 */ -var sortedLastIndex = createSortedIndex(true); +function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); +} export default sortedLastIndex; diff --git a/sortedLastIndexBy.js b/sortedLastIndexBy.js new file mode 100644 index 000000000..dee0af533 --- /dev/null +++ b/sortedLastIndexBy.js @@ -0,0 +1,26 @@ +import baseIteratee from './internal/baseIteratee'; +import baseSortedIndexBy from './internal/baseSortedIndexBy'; + +/** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted into `array`. + * @example + * + * // using the `_.property` iteratee shorthand + * _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x'); + * // => 1 + */ +function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, baseIteratee(iteratee), true); +} + +export default sortedLastIndexBy; diff --git a/sortedLastIndexOf.js b/sortedLastIndexOf.js new file mode 100644 index 000000000..2d5b98caf --- /dev/null +++ b/sortedLastIndexOf.js @@ -0,0 +1,30 @@ +import baseSortedIndex from './internal/baseSortedIndex'; +import eq from './eq'; + +/** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([1, 1, 2, 2], 2); + * // => 3 + */ +function sortedLastIndexOf(array, value) { + var length = array ? array.length : 0; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; +} + +export default sortedLastIndexOf; diff --git a/sortedUniq.js b/sortedUniq.js new file mode 100644 index 000000000..87b88345a --- /dev/null +++ b/sortedUniq.js @@ -0,0 +1,23 @@ +import baseSortedUniq from './internal/baseSortedUniq'; + +/** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ +function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; +} + +export default sortedUniq; diff --git a/sortedUniqBy.js b/sortedUniqBy.js new file mode 100644 index 000000000..d674c6f91 --- /dev/null +++ b/sortedUniqBy.js @@ -0,0 +1,25 @@ +import baseIteratee from './internal/baseIteratee'; +import baseSortedUniqBy from './internal/baseSortedUniqBy'; + +/** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.2] + */ +function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniqBy(array, baseIteratee(iteratee)) + : []; +} + +export default sortedUniqBy; diff --git a/split.js b/split.js new file mode 100644 index 000000000..94b7cf603 --- /dev/null +++ b/split.js @@ -0,0 +1,24 @@ +import toString from './toString'; + +/** + * Splits `string` by `separator`. + * + * **Note:** This method is based on [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the new array of string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ +function split(string, separator, limit) { + return toString(string).split(separator, limit); +} + +export default split; diff --git a/function/spread.js b/spread.js similarity index 90% rename from function/spread.js rename to spread.js index 3f8a05b60..684585eec 100644 --- a/function/spread.js +++ b/spread.js @@ -1,3 +1,5 @@ +import apply from './internal/apply'; + /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -5,7 +7,7 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * 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/Web/JavaScript/Reference/Operators/Spread_operator). + * **Note:** This method is based on the [spread operator](https://mdn.io/spread_operator). * * @static * @memberOf _ @@ -37,7 +39,7 @@ function spread(func) { throw new TypeError(FUNC_ERROR_TEXT); } return function(array) { - return func.apply(this, array); + return apply(func, this, array); }; } diff --git a/string/startCase.js b/startCase.js similarity index 77% rename from string/startCase.js rename to startCase.js index 854a91f8b..ec7dc7cac 100644 --- a/string/startCase.js +++ b/startCase.js @@ -1,4 +1,5 @@ -import createCompounder from '../internal/createCompounder'; +import capitalize from './capitalize'; +import createCompounder from './internal/createCompounder'; /** * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). @@ -20,7 +21,7 @@ import createCompounder from '../internal/createCompounder'; * // => 'Foo Bar' */ var startCase = createCompounder(function(result, word, index) { - return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1)); + return result + (index ? ' ' : '') + capitalize(word); }); export default startCase; diff --git a/string/startsWith.js b/startsWith.js similarity index 68% rename from string/startsWith.js rename to startsWith.js index df9a92862..064fcc6ab 100644 --- a/string/startsWith.js +++ b/startsWith.js @@ -1,7 +1,6 @@ -import baseToString from '../internal/baseToString'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeMin = Math.min; +import baseClamp from './internal/baseClamp'; +import toInteger from './toInteger'; +import toString from './toString'; /** * Checks if `string` starts with the given target string. @@ -25,11 +24,8 @@ var nativeMin = Math.min; * // => true */ function startsWith(string, target, position) { - string = baseToString(string); - position = position == null - ? 0 - : nativeMin(position < 0 ? 0 : (+position || 0), string.length); - + string = toString(string); + position = baseClamp(toInteger(position), 0, string.length); return string.lastIndexOf(target, position) == position; } diff --git a/string.default.js b/string.default.js new file mode 100644 index 000000000..5cc66f246 --- /dev/null +++ b/string.default.js @@ -0,0 +1,41 @@ +import camelCase from './camelCase'; +import capitalize from './capitalize'; +import deburr from './deburr'; +import endsWith from './endsWith'; +import escape from './escape'; +import escapeRegExp from './escapeRegExp'; +import kebabCase from './kebabCase'; +import lowerCase from './lowerCase'; +import lowerFirst from './lowerFirst'; +import pad from './pad'; +import padEnd from './padEnd'; +import padStart from './padStart'; +import parseInt from './parseInt'; +import repeat from './repeat'; +import replace from './replace'; +import snakeCase from './snakeCase'; +import split from './split'; +import startCase from './startCase'; +import startsWith from './startsWith'; +import template from './template'; +import templateSettings from './templateSettings'; +import toLower from './toLower'; +import toUpper from './toUpper'; +import trim from './trim'; +import trimEnd from './trimEnd'; +import trimStart from './trimStart'; +import truncate from './truncate'; +import unescape from './unescape'; +import upperCase from './upperCase'; +import upperFirst from './upperFirst'; +import words from './words'; + +export default { + camelCase, capitalize, deburr, endsWith, escape, + escapeRegExp, kebabCase, lowerCase, lowerFirst, pad, + padEnd, padStart, parseInt, repeat, replace, + snakeCase, split, startCase, startsWith, template, + templateSettings, toLower, toUpper, trim, trimEnd, + trimStart, truncate, unescape, upperCase, upperFirst, + words +}; diff --git a/string.js b/string.js index ade8e0d35..030db7a3f 100644 --- a/string.js +++ b/string.js @@ -1,49 +1,32 @@ -import camelCase from './string/camelCase'; -import capitalize from './string/capitalize'; -import deburr from './string/deburr'; -import endsWith from './string/endsWith'; -import escape from './string/escape'; -import escapeRegExp from './string/escapeRegExp'; -import kebabCase from './string/kebabCase'; -import pad from './string/pad'; -import padLeft from './string/padLeft'; -import padRight from './string/padRight'; -import parseInt from './string/parseInt'; -import repeat from './string/repeat'; -import snakeCase from './string/snakeCase'; -import startCase from './string/startCase'; -import startsWith from './string/startsWith'; -import template from './string/template'; -import templateSettings from './string/templateSettings'; -import trim from './string/trim'; -import trimLeft from './string/trimLeft'; -import trimRight from './string/trimRight'; -import trunc from './string/trunc'; -import unescape from './string/unescape'; -import words from './string/words'; - -export default { - 'camelCase': camelCase, - 'capitalize': capitalize, - 'deburr': deburr, - 'endsWith': endsWith, - 'escape': escape, - 'escapeRegExp': escapeRegExp, - 'kebabCase': kebabCase, - 'pad': pad, - 'padLeft': padLeft, - 'padRight': padRight, - 'parseInt': parseInt, - 'repeat': repeat, - 'snakeCase': snakeCase, - 'startCase': startCase, - 'startsWith': startsWith, - 'template': template, - 'templateSettings': templateSettings, - 'trim': trim, - 'trimLeft': trimLeft, - 'trimRight': trimRight, - 'trunc': trunc, - 'unescape': unescape, - 'words': words -}; +export { default as camelCase } from './camelCase'; +export { default as capitalize } from './capitalize'; +export { default as deburr } from './deburr'; +export { default as endsWith } from './endsWith'; +export { default as escape } from './escape'; +export { default as escapeRegExp } from './escapeRegExp'; +export { default as kebabCase } from './kebabCase'; +export { default as lowerCase } from './lowerCase'; +export { default as lowerFirst } from './lowerFirst'; +export { default as pad } from './pad'; +export { default as padEnd } from './padEnd'; +export { default as padStart } from './padStart'; +export { default as parseInt } from './parseInt'; +export { default as repeat } from './repeat'; +export { default as replace } from './replace'; +export { default as snakeCase } from './snakeCase'; +export { default as split } from './split'; +export { default as startCase } from './startCase'; +export { default as startsWith } from './startsWith'; +export { default as template } from './template'; +export { default as templateSettings } from './templateSettings'; +export { default as toLower } from './toLower'; +export { default as toUpper } from './toUpper'; +export { default as trim } from './trim'; +export { default as trimEnd } from './trimEnd'; +export { default as trimStart } from './trimStart'; +export { default as truncate } from './truncate'; +export { default as unescape } from './unescape'; +export { default as upperCase } from './upperCase'; +export { default as upperFirst } from './upperFirst'; +export { default as words } from './words'; +export { default as default } from './string.default'; diff --git a/string/escapeRegExp.js b/string/escapeRegExp.js deleted file mode 100644 index 407635428..000000000 --- a/string/escapeRegExp.js +++ /dev/null @@ -1,32 +0,0 @@ -import baseToString from '../internal/baseToString'; -import escapeRegExpChar from '../internal/escapeRegExpChar'; - -/** - * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns) - * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern). - */ -var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, - reHasRegExpChars = RegExp(reRegExpChars.source); - -/** - * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?", - * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`. - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escapeRegExp('[lodash](https://lodash.com/)'); - * // => '\[lodash\]\(https:\/\/lodash\.com\/\)' - */ -function escapeRegExp(string) { - string = baseToString(string); - return (string && reHasRegExpChars.test(string)) - ? string.replace(reRegExpChars, escapeRegExpChar) - : (string || '(?:)'); -} - -export default escapeRegExp; diff --git a/string/trim.js b/string/trim.js deleted file mode 100644 index 2aeaf77b9..000000000 --- a/string/trim.js +++ /dev/null @@ -1,42 +0,0 @@ -import baseToString from '../internal/baseToString'; -import charsLeftIndex from '../internal/charsLeftIndex'; -import charsRightIndex from '../internal/charsRightIndex'; -import isIterateeCall from '../internal/isIterateeCall'; -import trimmedLeftIndex from '../internal/trimmedLeftIndex'; -import trimmedRightIndex from '../internal/trimmedRightIndex'; - -/** - * Removes leading and trailing whitespace or specified characters from `string`. - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {string} Returns the trimmed string. - * @example - * - * _.trim(' abc '); - * // => 'abc' - * - * _.trim('-_-abc-_-', '_-'); - * // => 'abc' - * - * _.map([' foo ', ' bar '], _.trim); - * // => ['foo', 'bar'] - */ -function trim(string, chars, guard) { - var value = string; - string = baseToString(string); - if (!string) { - return string; - } - if (guard ? isIterateeCall(value, chars, guard) : chars == null) { - return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); - } - chars = (chars + ''); - return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); -} - -export default trim; diff --git a/string/trimLeft.js b/string/trimLeft.js deleted file mode 100644 index 88d78581e..000000000 --- a/string/trimLeft.js +++ /dev/null @@ -1,36 +0,0 @@ -import baseToString from '../internal/baseToString'; -import charsLeftIndex from '../internal/charsLeftIndex'; -import isIterateeCall from '../internal/isIterateeCall'; -import trimmedLeftIndex from '../internal/trimmedLeftIndex'; - -/** - * Removes leading whitespace or specified characters from `string`. - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {string} Returns the trimmed string. - * @example - * - * _.trimLeft(' abc '); - * // => 'abc ' - * - * _.trimLeft('-_-abc-_-', '_-'); - * // => 'abc-_-' - */ -function trimLeft(string, chars, guard) { - var value = string; - string = baseToString(string); - if (!string) { - return string; - } - if (guard ? isIterateeCall(value, chars, guard) : chars == null) { - return string.slice(trimmedLeftIndex(string)); - } - return string.slice(charsLeftIndex(string, (chars + ''))); -} - -export default trimLeft; diff --git a/string/trimRight.js b/string/trimRight.js deleted file mode 100644 index 31c4bdee9..000000000 --- a/string/trimRight.js +++ /dev/null @@ -1,36 +0,0 @@ -import baseToString from '../internal/baseToString'; -import charsRightIndex from '../internal/charsRightIndex'; -import isIterateeCall from '../internal/isIterateeCall'; -import trimmedRightIndex from '../internal/trimmedRightIndex'; - -/** - * Removes trailing whitespace or specified characters from `string`. - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to trim. - * @param {string} [chars=whitespace] The characters to trim. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {string} Returns the trimmed string. - * @example - * - * _.trimRight(' abc '); - * // => ' abc' - * - * _.trimRight('-_-abc-_-', '_-'); - * // => '-_-abc' - */ -function trimRight(string, chars, guard) { - var value = string; - string = baseToString(string); - if (!string) { - return string; - } - if (guard ? isIterateeCall(value, chars, guard) : chars == null) { - return string.slice(0, trimmedRightIndex(string) + 1); - } - return string.slice(0, charsRightIndex(string, (chars + '')) + 1); -} - -export default trimRight; diff --git a/string/trunc.js b/string/trunc.js deleted file mode 100644 index 2e7dcfde4..000000000 --- a/string/trunc.js +++ /dev/null @@ -1,105 +0,0 @@ -import baseToString from '../internal/baseToString'; -import isIterateeCall from '../internal/isIterateeCall'; -import isObject from '../lang/isObject'; -import isRegExp from '../lang/isRegExp'; - -/** Used as default options for `_.trunc`. */ -var DEFAULT_TRUNC_LENGTH = 30, - DEFAULT_TRUNC_OMISSION = '...'; - -/** Used to match `RegExp` flags from their coerced string values. */ -var reFlags = /\w*$/; - -/** - * Truncates `string` if it's longer than the given maximum string length. - * The last characters of the truncated string are replaced with the omission - * string which defaults to "...". - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to truncate. - * @param {Object|number} [options] The options object or maximum string length. - * @param {number} [options.length=30] The maximum string length. - * @param {string} [options.omission='...'] The string to indicate text is omitted. - * @param {RegExp|string} [options.separator] The separator pattern to truncate to. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {string} Returns the truncated string. - * @example - * - * _.trunc('hi-diddly-ho there, neighborino'); - * // => 'hi-diddly-ho there, neighbo...' - * - * _.trunc('hi-diddly-ho there, neighborino', 24); - * // => 'hi-diddly-ho there, n...' - * - * _.trunc('hi-diddly-ho there, neighborino', { - * 'length': 24, - * 'separator': ' ' - * }); - * // => 'hi-diddly-ho there,...' - * - * _.trunc('hi-diddly-ho there, neighborino', { - * 'length': 24, - * 'separator': /,? +/ - * }); - * // => 'hi-diddly-ho there...' - * - * _.trunc('hi-diddly-ho there, neighborino', { - * 'omission': ' [...]' - * }); - * // => 'hi-diddly-ho there, neig [...]' - */ -function trunc(string, options, guard) { - if (guard && isIterateeCall(string, options, guard)) { - options = undefined; - } - var length = DEFAULT_TRUNC_LENGTH, - omission = DEFAULT_TRUNC_OMISSION; - - if (options != null) { - if (isObject(options)) { - var separator = 'separator' in options ? options.separator : separator; - length = 'length' in options ? (+options.length || 0) : length; - omission = 'omission' in options ? baseToString(options.omission) : omission; - } else { - length = +options || 0; - } - } - string = baseToString(string); - if (length >= string.length) { - return string; - } - var end = length - omission.length; - if (end < 1) { - return omission; - } - var result = string.slice(0, end); - if (separator == null) { - return result + omission; - } - if (isRegExp(separator)) { - if (string.slice(end).search(separator)) { - var match, - newEnd, - substring = string.slice(0, end); - - if (!separator.global) { - separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g'); - } - separator.lastIndex = 0; - while ((match = separator.exec(substring))) { - newEnd = match.index; - } - result = result.slice(0, newEnd == null ? end : newEnd); - } - } else if (string.indexOf(separator, end) != end) { - var index = result.lastIndexOf(separator); - if (index > -1) { - result = result.slice(0, index); - } - } - return result + omission; -} - -export default trunc; diff --git a/string/words.js b/string/words.js deleted file mode 100644 index 7a898b7a0..000000000 --- a/string/words.js +++ /dev/null @@ -1,38 +0,0 @@ -import baseToString from '../internal/baseToString'; -import isIterateeCall from '../internal/isIterateeCall'; - -/** Used to match words to create compound words. */ -var reWords = (function() { - var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]', - lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+'; - - return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); -}()); - -/** - * Splits `string` into an array of its words. - * - * @static - * @memberOf _ - * @category String - * @param {string} [string=''] The string to inspect. - * @param {RegExp|string} [pattern] The pattern to match words. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {Array} Returns the words of `string`. - * @example - * - * _.words('fred, barney, & pebbles'); - * // => ['fred', 'barney', 'pebbles'] - * - * _.words('fred, barney, & pebbles', /[^, ]+/g); - * // => ['fred', 'barney', '&', 'pebbles'] - */ -function words(string, pattern, guard) { - if (guard && isIterateeCall(string, pattern, guard)) { - pattern = undefined; - } - string = baseToString(string); - return string.match(pattern || reWords) || []; -} - -export default words; diff --git a/subtract.js b/subtract.js new file mode 100644 index 000000000..1ed16fdcd --- /dev/null +++ b/subtract.js @@ -0,0 +1,26 @@ +/** + * Subtract two numbers. + * + * @static + * @memberOf _ + * @category Math + * @param {number} minuend The first number in a subtraction. + * @param {number} subtrahend The second number in a subtraction. + * @returns {number} Returns the difference. + * @example + * + * _.subtract(6, 4); + * // => 2 + */ +function subtract(minuend, subtrahend) { + var result; + if (minuend !== undefined) { + result = minuend; + } + if (subtrahend !== undefined) { + result = result === undefined ? subtrahend : (result - subtrahend); + } + return result; +} + +export default subtract; diff --git a/sum.js b/sum.js new file mode 100644 index 000000000..9bba5cfa2 --- /dev/null +++ b/sum.js @@ -0,0 +1,23 @@ +import baseSum from './internal/baseSum'; +import identity from './identity'; + +/** + * Computes the sum of the values in `array`. + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {number} Returns the sum. + * @example + * + * _.sum([4, 2, 8, 6]); + * // => 20 + */ +function sum(array) { + return (array && array.length) + ? baseSum(array, identity) + : undefined; +} + +export default sum; diff --git a/sumBy.js b/sumBy.js new file mode 100644 index 000000000..ce1774839 --- /dev/null +++ b/sumBy.js @@ -0,0 +1,32 @@ +import baseIteratee from './internal/baseIteratee'; +import baseSum from './internal/baseSum'; + +/** + * This method is like `_.sum` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the value to be summed. + * The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the sum. + * @example + * + * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; + * + * _.sumBy(objects, function(o) { return o.n; }); + * // => 20 + * + * // using the `_.property` iteratee shorthand + * _.sumBy(objects, 'n'); + * // => 20 + */ +function sumBy(array, iteratee) { + return (array && array.length) + ? baseSum(array, baseIteratee(iteratee)) + : undefined; +} + +export default sumBy; diff --git a/support.js b/support.js deleted file mode 100644 index 18f6803ee..000000000 --- a/support.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * An object environment feature flags. - * - * @static - * @memberOf _ - * @type Object - */ -var support = {}; - -export default support; diff --git a/array/rest.js b/tail.js similarity index 77% rename from array/rest.js rename to tail.js index 285876cf2..cf3dcc6ef 100644 --- a/array/rest.js +++ b/tail.js @@ -5,17 +5,16 @@ import drop from './drop'; * * @static * @memberOf _ - * @alias tail * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * - * _.rest([1, 2, 3]); + * _.tail([1, 2, 3]); * // => [2, 3] */ -function rest(array) { +function tail(array) { return drop(array, 1); } -export default rest; +export default tail; diff --git a/array/take.js b/take.js similarity index 64% rename from array/take.js rename to take.js index 6f50b8be4..bd5ae3446 100644 --- a/array/take.js +++ b/take.js @@ -1,5 +1,5 @@ -import baseSlice from '../internal/baseSlice'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseSlice from './internal/baseSlice'; +import toInteger from './toInteger'; /** * Creates a slice of `array` with `n` elements taken from the beginning. @@ -9,7 +9,7 @@ import isIterateeCall from '../internal/isIterateeCall'; * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -26,13 +26,10 @@ import isIterateeCall from '../internal/isIterateeCall'; * // => [] */ function take(array, n, guard) { - var length = array ? array.length : 0; - if (!length) { + if (!(array && array.length)) { return []; } - if (guard ? isIterateeCall(array, n, guard) : n == null) { - n = 1; - } + n = (guard || n === undefined) ? 1 : toInteger(n); return baseSlice(array, 0, n < 0 ? 0 : n); } diff --git a/array/takeRight.js b/takeRight.js similarity index 65% rename from array/takeRight.js rename to takeRight.js index 2a7a40f51..014642298 100644 --- a/array/takeRight.js +++ b/takeRight.js @@ -1,5 +1,5 @@ -import baseSlice from '../internal/baseSlice'; -import isIterateeCall from '../internal/isIterateeCall'; +import baseSlice from './internal/baseSlice'; +import toInteger from './toInteger'; /** * Creates a slice of `array` with `n` elements taken from the end. @@ -9,7 +9,7 @@ import isIterateeCall from '../internal/isIterateeCall'; * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * @@ -30,11 +30,9 @@ function takeRight(array, n, guard) { if (!length) { return []; } - if (guard ? isIterateeCall(array, n, guard) : n == null) { - n = 1; - } - n = length - (+n || 0); - return baseSlice(array, n < 0 ? 0 : n); + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); } export default takeRight; diff --git a/takeRightWhile.js b/takeRightWhile.js new file mode 100644 index 000000000..300758160 --- /dev/null +++ b/takeRightWhile.js @@ -0,0 +1,44 @@ +import baseIteratee from './internal/baseIteratee'; +import baseWhile from './internal/baseWhile'; + +/** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with three + * arguments: (value, index, array). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // using the `_.matches` iteratee shorthand + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // using the `_.property` iteratee shorthand + * _.takeRightWhile(users, 'active'); + * // => [] + */ +function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, baseIteratee(predicate, 3), false, true) + : []; +} + +export default takeRightWhile; diff --git a/takeWhile.js b/takeWhile.js new file mode 100644 index 000000000..a4baa4256 --- /dev/null +++ b/takeWhile.js @@ -0,0 +1,44 @@ +import baseIteratee from './internal/baseIteratee'; +import baseWhile from './internal/baseWhile'; + +/** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false}, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // using the `_.matches` iteratee shorthand + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // using the `_.matchesProperty` iteratee shorthand + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // using the `_.property` iteratee shorthand + * _.takeWhile(users, 'active'); + * // => [] + */ +function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, baseIteratee(predicate, 3)) + : []; +} + +export default takeWhile; diff --git a/chain/tap.js b/tap.js similarity index 54% rename from chain/tap.js rename to tap.js index 375bb647c..0a31e59d5 100644 --- a/chain/tap.js +++ b/tap.js @@ -1,15 +1,14 @@ /** * This method invokes `interceptor` and returns `value`. The interceptor is - * bound to `thisArg` and invoked with one argument; (value). The purpose of - * this method is to "tap into" a method chain in order to perform operations - * on intermediate results within the chain. + * invoked with one argument; (value). The purpose of this method is to "tap into" + * a method chain in order to perform operations on intermediate results within + * the chain. * * @static * @memberOf _ - * @category Chain + * @category Seq * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. - * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns `value`. * @example * @@ -21,8 +20,8 @@ * .value(); * // => [2, 1] */ -function tap(value, interceptor, thisArg) { - interceptor.call(thisArg, value); +function tap(value, interceptor) { + interceptor(value); return value; } diff --git a/string/template.js b/template.js similarity index 87% rename from string/template.js rename to template.js index 43802125e..e8778ca35 100644 --- a/string/template.js +++ b/template.js @@ -1,15 +1,14 @@ -import assignOwnDefaults from '../internal/assignOwnDefaults'; -import assignWith from '../internal/assignWith'; -import attempt from '../utility/attempt'; -import baseAssign from '../internal/baseAssign'; -import baseToString from '../internal/baseToString'; -import baseValues from '../internal/baseValues'; -import escapeStringChar from '../internal/escapeStringChar'; -import isError from '../lang/isError'; -import isIterateeCall from '../internal/isIterateeCall'; -import keys from '../object/keys'; -import reInterpolate from '../internal/reInterpolate'; +import assignInDefaults from './internal/assignInDefaults'; +import assignInWith from './assignInWith'; +import attempt from './attempt'; +import baseValues from './internal/baseValues'; +import escapeStringChar from './internal/escapeStringChar'; +import isError from './isError'; +import isIterateeCall from './internal/isIterateeCall'; +import keys from './keys'; +import reInterpolate from './internal/reInterpolate'; import templateSettings from './templateSettings'; +import toString from './toString'; /** Used to match empty string literals in compiled template source. */ var reEmptyStringLeading = /\b__p \+= '';/g, @@ -53,7 +52,7 @@ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; * @param {RegExp} [options.interpolate] The "interpolate" delimiter. * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. * @param {string} [options.variable] The data object variable name. - * @param- {Object} [otherOptions] Enables the legacy `options` param signature. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. * @returns {Function} Returns the compiled template function. * @example * @@ -121,18 +120,18 @@ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; * };\ * '); */ -function template(string, options, otherOptions) { +function template(string, options, guard) { // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/) // and Laura Doktorova's doT.js (https://github.com/olado/doT). var settings = templateSettings.imports._.templateSettings || templateSettings; - if (otherOptions && isIterateeCall(string, options, otherOptions)) { - options = otherOptions = undefined; + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; } - string = baseToString(string); - options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + string = toString(string); + options = assignInWith({}, options, settings, assignInDefaults); - var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), + var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); @@ -173,8 +172,8 @@ function template(string, options, otherOptions) { } index = offset + match.length; - // The JS engine embedded in Adobe products requires returning the `match` - // string in order to produce the correct `offset` value. + // The JS engine embedded in Adobe products needs `match` returned in + // order to produce the correct `offset` value. return match; }); diff --git a/string/templateSettings.js b/templateSettings.js similarity index 89% rename from string/templateSettings.js rename to templateSettings.js index a42393b71..5bce93057 100644 --- a/string/templateSettings.js +++ b/templateSettings.js @@ -1,7 +1,7 @@ import escape from './escape'; -import reEscape from '../internal/reEscape'; -import reEvaluate from '../internal/reEvaluate'; -import reInterpolate from '../internal/reInterpolate'; +import reEscape from './internal/reEscape'; +import reEvaluate from './internal/reEvaluate'; +import reInterpolate from './internal/reInterpolate'; /** * By default, the template delimiters used by lodash are like those in diff --git a/function/throttle.js b/throttle.js similarity index 71% rename from function/throttle.js rename to throttle.js index cd38564fe..acf7d58ea 100644 --- a/function/throttle.js +++ b/throttle.js @@ -1,5 +1,5 @@ import debounce from './debounce'; -import isObject from '../lang/isObject'; +import isObject from './isObject'; /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -7,10 +7,12 @@ var FUNC_ERROR_TEXT = 'Expected a function'; /** * Creates a throttled function that only invokes `func` at most once per * every `wait` milliseconds. The throttled function comes with a `cancel` - * method to cancel delayed invocations. Provide an options object to indicate - * that `func` should be invoked on the leading and/or trailing edge of the - * `wait` timeout. Subsequent calls to the throttled function return the - * result of the last `func` call. + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide an options object to indicate whether + * `func` should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the throttled function is @@ -36,11 +38,10 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes - * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { - * 'trailing': false - * })); + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); * - * // cancel a trailing throttled call + * // cancel a trailing throttled invocation * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { @@ -50,13 +51,11 @@ function throttle(func, wait, options) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } - if (options === false) { - leading = false; - } else if (isObject(options)) { + if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } - return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing }); + return debounce(func, wait, { 'leading': leading, 'maxWait': wait, 'trailing': trailing }); } export default throttle; diff --git a/chain/thru.js b/thru.js similarity index 73% rename from chain/thru.js rename to thru.js index e5e75637c..14813cf26 100644 --- a/chain/thru.js +++ b/thru.js @@ -3,10 +3,9 @@ * * @static * @memberOf _ - * @category Chain + * @category Seq * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. - * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns the result of `interceptor`. * @example * @@ -19,8 +18,8 @@ * .value(); * // => ['abc'] */ -function thru(value, interceptor, thisArg) { - return interceptor.call(thisArg, value); +function thru(value, interceptor) { + return interceptor(value); } export default thru; diff --git a/times.js b/times.js new file mode 100644 index 000000000..06cda5d92 --- /dev/null +++ b/times.js @@ -0,0 +1,50 @@ +import baseTimes from './internal/baseTimes'; +import toFunction from './internal/toFunction'; +import toInteger from './toInteger'; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Invokes the iteratee function `n` times, returning an array of the results + * of each invocation. The iteratee is invoked with one argument; (index). + * + * @static + * @memberOf _ + * @category Util + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of results. + * @example + * + * _.times(3, String); + * // => ['0', '1', '2'] + * + * _.times(4, _.constant(true)); + * // => [true, true, true, true] + */ +function times(n, iteratee) { + n = toInteger(n); + if (n < 1 || n > MAX_SAFE_INTEGER) { + return []; + } + var index = MAX_ARRAY_LENGTH, + length = nativeMin(n, MAX_ARRAY_LENGTH); + + iteratee = toFunction(iteratee); + n -= MAX_ARRAY_LENGTH; + + var result = baseTimes(length, iteratee); + while (++index < n) { + iteratee(index); + } + return result; +} + +export default times; diff --git a/toArray.js b/toArray.js new file mode 100644 index 000000000..4b3edd2fa --- /dev/null +++ b/toArray.js @@ -0,0 +1,57 @@ +import _Symbol from './internal/_Symbol'; +import copyArray from './internal/copyArray'; +import getTag from './internal/getTag'; +import isArrayLike from './isArrayLike'; +import isString from './isString'; +import iteratorToArray from './internal/iteratorToArray'; +import mapToArray from './internal/mapToArray'; +import setToArray from './internal/setToArray'; +import stringToArray from './internal/stringToArray'; +import values from './values'; + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + setTag = '[object Set]'; + +/** Built-in value references. */ +var iteratorSymbol = typeof (iteratorSymbol = _Symbol && _Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined; + +/** + * Converts `value` to an array. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ +function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (iteratorSymbol && value[iteratorSymbol]) { + return iteratorToArray(value[iteratorSymbol]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); +} + +export default toArray; diff --git a/toInteger.js b/toInteger.js new file mode 100644 index 000000000..879ef02fa --- /dev/null +++ b/toInteger.js @@ -0,0 +1,44 @@ +import toNumber from './toNumber'; + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0, + MAX_INTEGER = 1.7976931348623157e+308; + +/** + * Converts `value` to an integer. + * + * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3'); + * // => 3 + */ +function toInteger(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + var remainder = value % 1; + return value === value ? (remainder ? value - remainder : value) : 0; +} + +export default toInteger; diff --git a/toIterator.js b/toIterator.js new file mode 100644 index 000000000..c05ecf91d --- /dev/null +++ b/toIterator.js @@ -0,0 +1,22 @@ +/** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ +function wrapperToIterator() { + return this; +} + +export default wrapperToIterator; diff --git a/toJSON.js b/toJSON.js new file mode 100644 index 000000000..bca71bc8e --- /dev/null +++ b/toJSON.js @@ -0,0 +1 @@ +export { default } from './wrapperValue' diff --git a/toLength.js b/toLength.js new file mode 100644 index 000000000..82b240026 --- /dev/null +++ b/toLength.js @@ -0,0 +1,36 @@ +import baseClamp from './internal/baseClamp'; +import toInteger from './toInteger'; + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295; + +/** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @return {number} Returns the converted integer. + * @example + * + * _.toLength(3); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3'); + * // => 3 + */ +function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; +} + +export default toLength; diff --git a/toLower.js b/toLower.js new file mode 100644 index 000000000..4a8b452cf --- /dev/null +++ b/toLower.js @@ -0,0 +1,26 @@ +import toString from './toString'; + +/** + * Converts `string`, as a whole, to lower case. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.toLower('--Foo-Bar'); + * // => '--foo-bar' + * + * _.toLower('fooBar'); + * // => 'foobar' + * + * _.toLower('__FOO_BAR__'); + * // => '__foo_bar__' + */ +function toLower(value) { + return toString(value).toLowerCase(); +} + +export default toLower; diff --git a/toNumber.js b/toNumber.js new file mode 100644 index 000000000..ba7d85b49 --- /dev/null +++ b/toNumber.js @@ -0,0 +1,59 @@ +import isFunction from './isFunction'; +import isObject from './isObject'; + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** Used to detect bad signed hexadecimal string values. */ +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + +/** Used to detect binary string values. */ +var reIsBinary = /^0b[01]+$/i; + +/** Used to detect octal string values. */ +var reIsOctal = /^0o[0-7]+$/i; + +/** Built-in method references without a dependency on `root`. */ +var freeParseInt = parseInt; + +/** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3); + * // => 3 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3'); + * // => 3 + */ +function toNumber(value) { + if (isObject(value)) { + var other = isFunction(value.valueOf) ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); +} + +export default toNumber; diff --git a/toPairs.js b/toPairs.js new file mode 100644 index 000000000..3aefd1751 --- /dev/null +++ b/toPairs.js @@ -0,0 +1,28 @@ +import baseToPairs from './internal/baseToPairs'; +import keys from './keys'; + +/** + * Creates an array of own enumerable key-value pairs for `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the new array of key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ +function toPairs(object) { + return baseToPairs(object, keys(object)); +} + +export default toPairs; diff --git a/toPairsIn.js b/toPairsIn.js new file mode 100644 index 000000000..5b198c4c7 --- /dev/null +++ b/toPairsIn.js @@ -0,0 +1,28 @@ +import baseToPairs from './internal/baseToPairs'; +import keysIn from './keysIn'; + +/** + * Creates an array of own and inherited enumerable key-value pairs for `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the new array of key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 1]] (iteration order is not guaranteed) + */ +function toPairsIn(object) { + return baseToPairs(object, keysIn(object)); +} + +export default toPairsIn; diff --git a/toPath.js b/toPath.js new file mode 100644 index 000000000..fa0bd118b --- /dev/null +++ b/toPath.js @@ -0,0 +1,34 @@ +import arrayMap from './internal/arrayMap'; +import isArray from './isArray'; +import stringToPath from './internal/stringToPath'; + +/** + * Converts `value` to a property path array. + * + * @static + * @memberOf _ + * @category Util + * @param {*} value The value to convert. + * @returns {Array} Returns the new property path array. + * @example + * + * _.toPath('a.b.c'); + * // => ['a', 'b', 'c'] + * + * _.toPath('a[0].b.c'); + * // => ['a', '0', 'b', 'c'] + * + * var path = ['a', 'b', 'c'], + * newPath = _.toPath(path); + * + * console.log(newPath); + * // => ['a', 'b', 'c'] + * + * console.log(path === newPath); + * // => false + */ +function toPath(value) { + return isArray(value) ? arrayMap(value, String) : stringToPath(value); +} + +export default toPath; diff --git a/lang/toPlainObject.js b/toPlainObject.js similarity index 82% rename from lang/toPlainObject.js rename to toPlainObject.js index 8ddb4d58f..9bab37ad7 100644 --- a/lang/toPlainObject.js +++ b/toPlainObject.js @@ -1,5 +1,5 @@ -import baseCopy from '../internal/baseCopy'; -import keysIn from '../object/keysIn'; +import copyObject from './internal/copyObject'; +import keysIn from './keysIn'; /** * Converts `value` to a plain object flattening inherited enumerable @@ -25,7 +25,7 @@ import keysIn from '../object/keysIn'; * // => { 'a': 1, 'b': 2, 'c': 3 } */ function toPlainObject(value) { - return baseCopy(value, keysIn(value)); + return copyObject(value, keysIn(value)); } export default toPlainObject; diff --git a/toSafeInteger.js b/toSafeInteger.js new file mode 100644 index 000000000..c608ee09a --- /dev/null +++ b/toSafeInteger.js @@ -0,0 +1,34 @@ +import baseClamp from './internal/baseClamp'; +import toInteger from './toInteger'; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3'); + * // => 3 + */ +function toSafeInteger(value) { + return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); +} + +export default toSafeInteger; diff --git a/toString.js b/toString.js new file mode 100644 index 000000000..b0ea461d1 --- /dev/null +++ b/toString.js @@ -0,0 +1,46 @@ +import _Symbol from './internal/_Symbol'; +import isSymbol from './isSymbol'; + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = _Symbol ? _Symbol.prototype : undefined, + symbolToString = _Symbol ? symbolProto.toString : undefined; + +/** + * Converts `value` to a string if it's not one. An empty string is returned + * for `null` and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (value == null) { + return ''; + } + if (isSymbol(value)) { + return _Symbol ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +export default toString; diff --git a/toUpper.js b/toUpper.js new file mode 100644 index 000000000..b1da10938 --- /dev/null +++ b/toUpper.js @@ -0,0 +1,26 @@ +import toString from './toString'; + +/** + * Converts `string`, as a whole, to upper case. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the upper cased string. + * @example + * + * _.toUpper('--foo-bar'); + * // => '--FOO-BAR' + * + * _.toUpper('fooBar'); + * // => 'FOOBAR' + * + * _.toUpper('__foo_bar__'); + * // => '__FOO_BAR__' + */ +function toUpper(value) { + return toString(value).toUpperCase(); +} + +export default toUpper; diff --git a/object/transform.js b/transform.js similarity index 58% rename from object/transform.js rename to transform.js index d2bee9b84..fdbe2c7d8 100644 --- a/object/transform.js +++ b/transform.js @@ -1,19 +1,19 @@ -import arrayEach from '../internal/arrayEach'; -import baseCallback from '../internal/baseCallback'; -import baseCreate from '../internal/baseCreate'; -import baseForOwn from '../internal/baseForOwn'; -import isArray from '../lang/isArray'; -import isFunction from '../lang/isFunction'; -import isObject from '../lang/isObject'; -import isTypedArray from '../lang/isTypedArray'; +import arrayEach from './internal/arrayEach'; +import baseCreate from './internal/baseCreate'; +import baseForOwn from './internal/baseForOwn'; +import baseIteratee from './internal/baseIteratee'; +import isArray from './isArray'; +import isFunction from './isFunction'; +import isObject from './isObject'; +import isTypedArray from './isTypedArray'; /** * An alternative to `_.reduce`; this method transforms `object` to a new * `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). Iteratee functions - * may exit iteration early by explicitly returning `false`. + * the `accumulator` object. The iteratee is invoked with four arguments: + * (accumulator, value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. * * @static * @memberOf _ @@ -21,7 +21,6 @@ import isTypedArray from '../lang/isTypedArray'; * @param {Array|Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * @@ -31,14 +30,14 @@ import isTypedArray from '../lang/isTypedArray'; * }); * // => [4, 9] * - * _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) { - * result[key] = n * 3; + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); * }); - * // => { 'a': 3, 'b': 6 } + * // => { '1': ['a', 'c'], '2': ['b'] } */ -function transform(object, iteratee, accumulator, thisArg) { +function transform(object, iteratee, accumulator) { var isArr = isArray(object) || isTypedArray(object); - iteratee = baseCallback(iteratee, thisArg, 4); + iteratee = baseIteratee(iteratee, 4); if (accumulator == null) { if (isArr || isObject(object)) { diff --git a/trim.js b/trim.js new file mode 100644 index 000000000..adc9ad8f3 --- /dev/null +++ b/trim.js @@ -0,0 +1,48 @@ +import charsEndIndex from './internal/charsEndIndex'; +import charsStartIndex from './internal/charsStartIndex'; +import stringToArray from './internal/stringToArray'; +import toString from './toString'; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** + * Removes leading and trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trim(' abc '); + * // => 'abc' + * + * _.trim('-_-abc-_-', '_-'); + * // => 'abc' + * + * _.map([' foo ', ' bar '], _.trim); + * // => ['foo', 'bar'] + */ +function trim(string, chars, guard) { + string = toString(string); + if (!string) { + return string; + } + if (guard || chars === undefined) { + return string.replace(reTrim, ''); + } + chars = (chars + ''); + if (!chars) { + return string; + } + var strSymbols = stringToArray(string), + chrSymbols = stringToArray(chars); + + return strSymbols.slice(charsStartIndex(strSymbols, chrSymbols), charsEndIndex(strSymbols, chrSymbols) + 1).join(''); +} + +export default trim; diff --git a/trimEnd.js b/trimEnd.js new file mode 100644 index 000000000..bf10e4902 --- /dev/null +++ b/trimEnd.js @@ -0,0 +1,42 @@ +import charsEndIndex from './internal/charsEndIndex'; +import stringToArray from './internal/stringToArray'; +import toString from './toString'; + +/** Used to match leading and trailing whitespace. */ +var reTrimEnd = /\s+$/; + +/** + * Removes trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trimEnd(' abc '); + * // => ' abc' + * + * _.trimEnd('-_-abc-_-', '_-'); + * // => '-_-abc' + */ +function trimEnd(string, chars, guard) { + string = toString(string); + if (!string) { + return string; + } + if (guard || chars === undefined) { + return string.replace(reTrimEnd, ''); + } + chars = (chars + ''); + if (!chars) { + return string; + } + var strSymbols = stringToArray(string); + return strSymbols.slice(0, charsEndIndex(strSymbols, stringToArray(chars)) + 1).join(''); +} + +export default trimEnd; diff --git a/trimStart.js b/trimStart.js new file mode 100644 index 000000000..203873bb5 --- /dev/null +++ b/trimStart.js @@ -0,0 +1,42 @@ +import charsStartIndex from './internal/charsStartIndex'; +import stringToArray from './internal/stringToArray'; +import toString from './toString'; + +/** Used to match leading and trailing whitespace. */ +var reTrimStart = /^\s+/; + +/** + * Removes leading whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trimStart(' abc '); + * // => 'abc ' + * + * _.trimStart('-_-abc-_-', '_-'); + * // => 'abc-_-' + */ +function trimStart(string, chars, guard) { + string = toString(string); + if (!string) { + return string; + } + if (guard || chars === undefined) { + return string.replace(reTrimStart, ''); + } + chars = (chars + ''); + if (!chars) { + return string; + } + var strSymbols = stringToArray(string); + return strSymbols.slice(charsStartIndex(strSymbols, stringToArray(chars))).join(''); +} + +export default trimStart; diff --git a/truncate.js b/truncate.js new file mode 100644 index 000000000..7cc181fb3 --- /dev/null +++ b/truncate.js @@ -0,0 +1,118 @@ +import isObject from './isObject'; +import isRegExp from './isRegExp'; +import stringSize from './internal/stringSize'; +import stringToArray from './internal/stringToArray'; +import toInteger from './toInteger'; +import toString from './toString'; + +/** Used as default options for `_.truncate`. */ +var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Truncates `string` if it's longer than the given maximum string length. + * The last characters of the truncated string are replaced with the omission + * string which defaults to "...". + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to truncate. + * @param {Object} [options] The options object. + * @param {number} [options.length=30] The maximum string length. + * @param {string} [options.omission='...'] The string to indicate text is omitted. + * @param {RegExp|string} [options.separator] The separator pattern to truncate to. + * @returns {string} Returns the truncated string. + * @example + * + * _.truncate('hi-diddly-ho there, neighborino'); + * // => 'hi-diddly-ho there, neighbo...' + * + * _.truncate('hi-diddly-ho there, neighborino', { + * 'length': 24, + * 'separator': ' ' + * }); + * // => 'hi-diddly-ho there,...' + * + * _.truncate('hi-diddly-ho there, neighborino', { + * 'length': 24, + * 'separator': /,? +/ + * }); + * // => 'hi-diddly-ho there...' + * + * _.truncate('hi-diddly-ho there, neighborino', { + * 'omission': ' [...]' + * }); + * // => 'hi-diddly-ho there, neig [...]' + */ +function truncate(string, options) { + var length = DEFAULT_TRUNC_LENGTH, + omission = DEFAULT_TRUNC_OMISSION; + + if (isObject(options)) { + var separator = 'separator' in options ? options.separator : separator; + length = 'length' in options ? toInteger(options.length) : length; + omission = 'omission' in options ? toString(options.omission) : omission; + } + string = toString(string); + + var strLength = string.length; + if (reHasComplexSymbol.test(string)) { + var strSymbols = stringToArray(string); + strLength = strSymbols.length; + } + if (length >= strLength) { + return string; + } + var end = length - stringSize(omission); + if (end < 1) { + return omission; + } + var result = strSymbols + ? strSymbols.slice(0, end).join('') + : string.slice(0, end); + + if (separator === undefined) { + return result + omission; + } + if (strSymbols) { + end += (result.length - end); + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, + substring = result; + + if (!separator.global) { + separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g'); + } + separator.lastIndex = 0; + while ((match = separator.exec(substring))) { + var newEnd = match.index; + } + result = result.slice(0, newEnd === undefined ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; +} + +export default truncate; diff --git a/unary.js b/unary.js new file mode 100644 index 000000000..e92aba57e --- /dev/null +++ b/unary.js @@ -0,0 +1,21 @@ +import ary from './ary'; + +/** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ +function unary(func) { + return ary(func, 1); +} + +export default unary; diff --git a/string/unescape.js b/unescape.js similarity index 86% rename from string/unescape.js rename to unescape.js index 556af6350..488cf9982 100644 --- a/string/unescape.js +++ b/unescape.js @@ -1,5 +1,5 @@ -import baseToString from '../internal/baseToString'; -import unescapeHtmlChar from '../internal/unescapeHtmlChar'; +import toString from './toString'; +import unescapeHtmlChar from './internal/unescapeHtmlChar'; /** Used to match HTML entities and HTML characters. */ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, @@ -24,7 +24,7 @@ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, * // => 'fred, barney, & pebbles' */ function unescape(string) { - string = baseToString(string); + string = toString(string); return (string && reHasEscapedHtml.test(string)) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; diff --git a/array/union.js b/union.js similarity index 66% rename from array/union.js rename to union.js index 226f956a2..88138f7e4 100644 --- a/array/union.js +++ b/union.js @@ -1,6 +1,6 @@ -import baseFlatten from '../internal/baseFlatten'; -import baseUniq from '../internal/baseUniq'; -import restParam from '../function/restParam'; +import baseFlatten from './internal/baseFlatten'; +import baseUniq from './internal/baseUniq'; +import rest from './rest'; /** * Creates an array of unique values, in order, from all of the provided arrays @@ -14,10 +14,10 @@ import restParam from '../function/restParam'; * @returns {Array} Returns the new array of combined values. * @example * - * _.union([1, 2], [4, 2], [2, 1]); - * // => [1, 2, 4] + * _.union([2, 1], [4, 2], [1, 2]); + * // => [2, 1, 4] */ -var union = restParam(function(arrays) { +var union = rest(function(arrays) { return baseUniq(baseFlatten(arrays, false, true)); }); diff --git a/unionBy.js b/unionBy.js new file mode 100644 index 000000000..2a8c16825 --- /dev/null +++ b/unionBy.js @@ -0,0 +1,36 @@ +import baseFlatten from './internal/baseFlatten'; +import baseIteratee from './internal/baseIteratee'; +import baseUniq from './internal/baseUniq'; +import isArrayLikeObject from './isArrayLikeObject'; +import last from './last'; +import rest from './rest'; + +/** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by which + * uniqueness is computed. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor); + * // => [2.1, 1.2, 4.3] + * + * // using the `_.property` iteratee shorthand + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ +var unionBy = rest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, false, true), baseIteratee(iteratee)); +}); + +export default unionBy; diff --git a/unionWith.js b/unionWith.js new file mode 100644 index 000000000..78dcf83af --- /dev/null +++ b/unionWith.js @@ -0,0 +1,34 @@ +import baseFlatten from './internal/baseFlatten'; +import baseUniq from './internal/baseUniq'; +import isArrayLikeObject from './isArrayLikeObject'; +import last from './last'; +import rest from './rest'; + +/** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ +var unionWith = rest(function(arrays) { + var comparator = last(arrays); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return baseUniq(baseFlatten(arrays, false, true), undefined, comparator); +}); + +export default unionWith; diff --git a/uniq.js b/uniq.js new file mode 100644 index 000000000..24164bfde --- /dev/null +++ b/uniq.js @@ -0,0 +1,25 @@ +import baseUniq from './internal/baseUniq'; + +/** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ +function uniq(array) { + return (array && array.length) + ? baseUniq(array) + : []; +} + +export default uniq; diff --git a/uniqBy.js b/uniqBy.js new file mode 100644 index 000000000..e3a6e74b7 --- /dev/null +++ b/uniqBy.js @@ -0,0 +1,30 @@ +import baseIteratee from './internal/baseIteratee'; +import baseUniq from './internal/baseUniq'; + +/** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // using the `_.property` iteratee shorthand + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ +function uniqBy(array, iteratee) { + return (array && array.length) + ? baseUniq(array, baseIteratee(iteratee)) + : []; +} + +export default uniqBy; diff --git a/uniqWith.js b/uniqWith.js new file mode 100644 index 000000000..1f36cf699 --- /dev/null +++ b/uniqWith.js @@ -0,0 +1,27 @@ +import baseUniq from './internal/baseUniq'; + +/** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The comparator is invoked with + * two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ +function uniqWith(array, comparator) { + return (array && array.length) + ? baseUniq(array, undefined, comparator) + : []; +} + +export default uniqWith; diff --git a/utility/uniqueId.js b/uniqueId.js similarity index 80% rename from utility/uniqueId.js rename to uniqueId.js index eb414fc72..e416f971b 100644 --- a/utility/uniqueId.js +++ b/uniqueId.js @@ -1,4 +1,4 @@ -import baseToString from '../internal/baseToString'; +import toString from './toString'; /** Used to generate unique IDs. */ var idCounter = 0; @@ -8,7 +8,7 @@ var idCounter = 0; * * @static * @memberOf _ - * @category Utility + * @category Util * @param {string} [prefix] The value to prefix the ID with. * @returns {string} Returns the unique ID. * @example @@ -21,7 +21,7 @@ var idCounter = 0; */ function uniqueId(prefix) { var id = ++idCounter; - return baseToString(prefix) + id; + return toString(prefix) + id; } export default uniqueId; diff --git a/unset.js b/unset.js new file mode 100644 index 000000000..6f184b2e4 --- /dev/null +++ b/unset.js @@ -0,0 +1,31 @@ +import baseUnset from './internal/baseUnset'; + +/** + * Removes the property at `path` of `object`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ +function unset(object, path) { + return object == null ? true : baseUnset(object, path); +} + +export default unset; diff --git a/array/unzip.js b/unzip.js similarity index 62% rename from array/unzip.js rename to unzip.js index 841b8174f..bda6c3f3b 100644 --- a/array/unzip.js +++ b/unzip.js @@ -1,9 +1,10 @@ -import arrayFilter from '../internal/arrayFilter'; -import arrayMap from '../internal/arrayMap'; -import baseProperty from '../internal/baseProperty'; -import isArrayLike from '../internal/isArrayLike'; +import arrayFilter from './internal/arrayFilter'; +import arrayMap from './internal/arrayMap'; +import baseProperty from './internal/baseProperty'; +import baseTimes from './internal/baseTimes'; +import isArrayLikeObject from './isArrayLikeObject'; -/* Native method references for those with the same name as other `lodash` methods. */ +/* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; /** @@ -28,20 +29,16 @@ function unzip(array) { if (!(array && array.length)) { return []; } - var index = -1, - length = 0; - + var length = 0; array = arrayFilter(array, function(group) { - if (isArrayLike(group)) { + if (isArrayLikeObject(group)) { length = nativeMax(group.length, length); return true; } }); - var result = Array(length); - while (++index < length) { - result[index] = arrayMap(array, baseProperty(index)); - } - return result; + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); } export default unzip; diff --git a/unzipWith.js b/unzipWith.js new file mode 100644 index 000000000..99f9ed634 --- /dev/null +++ b/unzipWith.js @@ -0,0 +1,37 @@ +import apply from './internal/apply'; +import arrayMap from './internal/arrayMap'; +import unzip from './unzip'; + +/** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ +function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); +} + +export default unzipWith; diff --git a/upperCase.js b/upperCase.js new file mode 100644 index 000000000..6eca5dd2c --- /dev/null +++ b/upperCase.js @@ -0,0 +1,26 @@ +import createCompounder from './internal/createCompounder'; + +/** + * Converts `string`, as space separated words, to upper case. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the upper cased string. + * @example + * + * _.upperCase('--foo-bar'); + * // => 'FOO BAR' + * + * _.upperCase('fooBar'); + * // => 'FOO BAR' + * + * _.upperCase('__foo_bar__'); + * // => 'FOO BAR' + */ +var upperCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toUpperCase(); +}); + +export default upperCase; diff --git a/upperFirst.js b/upperFirst.js new file mode 100644 index 000000000..8cd4e8bcb --- /dev/null +++ b/upperFirst.js @@ -0,0 +1,21 @@ +import createCaseFirst from './internal/createCaseFirst'; + +/** + * Converts the first character of `string` to upper case. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.upperFirst('fred'); + * // => 'Fred' + * + * _.upperFirst('FRED'); + * // => 'FRED' + */ +var upperFirst = createCaseFirst('toUpperCase'); + +export default upperFirst; diff --git a/util.default.js b/util.default.js new file mode 100644 index 000000000..d2b93e508 --- /dev/null +++ b/util.default.js @@ -0,0 +1,35 @@ +import attempt from './attempt'; +import bindAll from './bindAll'; +import cond from './cond'; +import conforms from './conforms'; +import constant from './constant'; +import flow from './flow'; +import flowRight from './flowRight'; +import identity from './identity'; +import iteratee from './iteratee'; +import matches from './matches'; +import matchesProperty from './matchesProperty'; +import method from './method'; +import methodOf from './methodOf'; +import mixin from './mixin'; +import noop from './noop'; +import nthArg from './nthArg'; +import over from './over'; +import overEvery from './overEvery'; +import overSome from './overSome'; +import property from './property'; +import propertyOf from './propertyOf'; +import range from './range'; +import rangeRight from './rangeRight'; +import times from './times'; +import toPath from './toPath'; +import uniqueId from './uniqueId'; + +export default { + attempt, bindAll, cond, conforms, constant, + flow, flowRight, identity, iteratee, matches, + matchesProperty, method, methodOf, mixin, noop, + nthArg, over, overEvery, overSome, property, + propertyOf, range, rangeRight, times, toPath, + uniqueId +}; diff --git a/util.js b/util.js new file mode 100644 index 000000000..21aea586c --- /dev/null +++ b/util.js @@ -0,0 +1,27 @@ +export { default as attempt } from './attempt'; +export { default as bindAll } from './bindAll'; +export { default as cond } from './cond'; +export { default as conforms } from './conforms'; +export { default as constant } from './constant'; +export { default as flow } from './flow'; +export { default as flowRight } from './flowRight'; +export { default as identity } from './identity'; +export { default as iteratee } from './iteratee'; +export { default as matches } from './matches'; +export { default as matchesProperty } from './matchesProperty'; +export { default as method } from './method'; +export { default as methodOf } from './methodOf'; +export { default as mixin } from './mixin'; +export { default as noop } from './noop'; +export { default as nthArg } from './nthArg'; +export { default as over } from './over'; +export { default as overEvery } from './overEvery'; +export { default as overSome } from './overSome'; +export { default as property } from './property'; +export { default as propertyOf } from './propertyOf'; +export { default as range } from './range'; +export { default as rangeRight } from './rangeRight'; +export { default as times } from './times'; +export { default as toPath } from './toPath'; +export { default as uniqueId } from './uniqueId'; +export { default as default } from './util.default'; diff --git a/utility.js b/utility.js deleted file mode 100644 index dd47a8245..000000000 --- a/utility.js +++ /dev/null @@ -1,35 +0,0 @@ -import attempt from './utility/attempt'; -import callback from './utility/callback'; -import constant from './utility/constant'; -import identity from './utility/identity'; -import iteratee from './utility/iteratee'; -import matches from './utility/matches'; -import matchesProperty from './utility/matchesProperty'; -import method from './utility/method'; -import methodOf from './utility/methodOf'; -import mixin from './utility/mixin'; -import noop from './utility/noop'; -import property from './utility/property'; -import propertyOf from './utility/propertyOf'; -import range from './utility/range'; -import times from './utility/times'; -import uniqueId from './utility/uniqueId'; - -export default { - 'attempt': attempt, - 'callback': callback, - 'constant': constant, - 'identity': identity, - 'iteratee': iteratee, - 'matches': matches, - 'matchesProperty': matchesProperty, - 'method': method, - 'methodOf': methodOf, - 'mixin': mixin, - 'noop': noop, - 'property': property, - 'propertyOf': propertyOf, - 'range': range, - 'times': times, - 'uniqueId': uniqueId -}; diff --git a/utility/callback.js b/utility/callback.js deleted file mode 100644 index bd5d9c60a..000000000 --- a/utility/callback.js +++ /dev/null @@ -1,53 +0,0 @@ -import baseCallback from '../internal/baseCallback'; -import isIterateeCall from '../internal/isIterateeCall'; -import isObjectLike from '../internal/isObjectLike'; -import matches from './matches'; - -/** - * Creates a function that invokes `func` with the `this` binding of `thisArg` - * and arguments of the created function. If `func` is a property name the - * created callback returns the property value for a given element. If `func` - * is an object the created callback returns `true` for elements that contain - * the equivalent object properties, otherwise it returns `false`. - * - * @static - * @memberOf _ - * @alias iteratee - * @category Utility - * @param {*} [func=_.identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of `func`. - * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. - * @returns {Function} Returns the callback. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } - * ]; - * - * // wrap to create custom callback shorthands - * _.callback = _.wrap(_.callback, function(callback, func, thisArg) { - * var match = /^(.+?)__([gl]t)(.+)$/.exec(func); - * if (!match) { - * return callback(func, thisArg); - * } - * return function(object) { - * return match[2] == 'gt' - * ? object[match[1]] > match[3] - * : object[match[1]] < match[3]; - * }; - * }); - * - * _.filter(users, 'age__gt36'); - * // => [{ 'user': 'fred', 'age': 40 }] - */ -function callback(func, thisArg, guard) { - if (guard && isIterateeCall(func, thisArg, guard)) { - thisArg = undefined; - } - return isObjectLike(func) - ? matches(func) - : baseCallback(func, thisArg); -} - -export default callback; diff --git a/utility/iteratee.js b/utility/iteratee.js deleted file mode 100644 index aeb12e4af..000000000 --- a/utility/iteratee.js +++ /dev/null @@ -1,2 +0,0 @@ -import callback from './callback' -export default callback; diff --git a/utility/matches.js b/utility/matches.js deleted file mode 100644 index aa29d1e19..000000000 --- a/utility/matches.js +++ /dev/null @@ -1,33 +0,0 @@ -import baseClone from '../internal/baseClone'; -import baseMatches from '../internal/baseMatches'; - -/** - * Creates a function that performs a deep comparison between a given object - * and `source`, returning `true` if the given object has equivalent property - * values, else `false`. - * - * **Note:** This method supports comparing arrays, booleans, `Date` objects, - * numbers, `Object` objects, regexes, and strings. Objects are compared by - * their own, not inherited, enumerable properties. For comparing a single - * own or inherited property value see `_.matchesProperty`. - * - * @static - * @memberOf _ - * @category Utility - * @param {Object} source The object of property values to match. - * @returns {Function} Returns the new function. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false } - * ]; - * - * _.filter(users, _.matches({ 'age': 40, 'active': false })); - * // => [{ 'user': 'fred', 'age': 40, 'active': false }] - */ -function matches(source) { - return baseMatches(baseClone(source, true)); -} - -export default matches; diff --git a/utility/mixin.js b/utility/mixin.js deleted file mode 100644 index d4eb600f4..000000000 --- a/utility/mixin.js +++ /dev/null @@ -1,82 +0,0 @@ -import arrayCopy from '../internal/arrayCopy'; -import arrayPush from '../internal/arrayPush'; -import baseFunctions from '../internal/baseFunctions'; -import isFunction from '../lang/isFunction'; -import isObject from '../lang/isObject'; -import keys from '../object/keys'; - -/** - * Adds all own enumerable function properties of a source object to the - * 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 to - * avoid conflicts caused by modifying the original. - * - * @static - * @memberOf _ - * @category Utility - * @param {Function|Object} [object=lodash] The destination object. - * @param {Object} source The object of functions to add. - * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added - * are chainable. - * @returns {Function|Object} Returns `object`. - * @example - * - * function vowels(string) { - * return _.filter(string, function(v) { - * return /[aeiou]/i.test(v); - * }); - * } - * - * _.mixin({ 'vowels': vowels }); - * _.vowels('fred'); - * // => ['e'] - * - * _('fred').vowels().value(); - * // => ['e'] - * - * _.mixin({ 'vowels': vowels }, { 'chain': false }); - * _('fred').vowels(); - * // => ['e'] - */ -function mixin(object, source, options) { - var methodNames = baseFunctions(source, keys(source)); - - var chain = true, - index = -1, - isFunc = isFunction(object), - length = methodNames.length; - - if (options === false) { - chain = false; - } else if (isObject(options) && 'chain' in options) { - chain = options.chain; - } - while (++index < length) { - var methodName = methodNames[index], - func = source[methodName]; - - object[methodName] = func; - if (isFunc) { - object.prototype[methodName] = (function(func) { - return function() { - var chainAll = this.__chain__; - if (chain || chainAll) { - var result = object(this.__wrapped__), - actions = result.__actions__ = arrayCopy(this.__actions__); - - actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); - result.__chain__ = chainAll; - return result; - } - return func.apply(object, arrayPush([this.value()], arguments)); - }; - }(func)); - } - } - return object; -} - -export default mixin; diff --git a/utility/range.js b/utility/range.js deleted file mode 100644 index b8c31a7a2..000000000 --- a/utility/range.js +++ /dev/null @@ -1,66 +0,0 @@ -import isIterateeCall from '../internal/isIterateeCall'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeCeil = Math.ceil, - nativeMax = Math.max; - -/** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to, but not including, `end`. If `end` is not specified it's - * set to `start` with `start` then set to `0`. If `end` is less than `start` - * a zero-length range is created unless a negative `step` is specified. - * - * @static - * @memberOf _ - * @category Utility - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns the new array of numbers. - * @example - * - * _.range(4); - * // => [0, 1, 2, 3] - * - * _.range(1, 5); - * // => [1, 2, 3, 4] - * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] - * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] - * - * _.range(1, 4, 0); - * // => [1, 1, 1] - * - * _.range(0); - * // => [] - */ -function range(start, end, step) { - if (step && isIterateeCall(start, end, step)) { - end = step = undefined; - } - start = +start || 0; - step = step == null ? 1 : (+step || 0); - - if (end == null) { - end = start; - start = 0; - } else { - end = +end || 0; - } - // Use `Array(length)` so engines like Chakra and V8 avoid slower modes. - // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details. - var index = -1, - length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), - result = Array(length); - - while (++index < length) { - result[index] = start; - start += step; - } - return result; -} - -export default range; diff --git a/utility/times.js b/utility/times.js deleted file mode 100644 index c4a2c2cde..000000000 --- a/utility/times.js +++ /dev/null @@ -1,61 +0,0 @@ -import bindCallback from '../internal/bindCallback'; -import root from '../internal/root'; - -/* Native method references for those with the same name as other `lodash` methods. */ -var nativeFloor = Math.floor, - nativeIsFinite = root.isFinite, - nativeMin = Math.min; - -/** Used as references for the maximum length and index of an array. */ -var MAX_ARRAY_LENGTH = 4294967295; - -/** - * Invokes the iteratee function `n` times, returning an array of the results - * of each invocation. The `iteratee` is bound to `thisArg` and invoked with - * one argument; (index). - * - * @static - * @memberOf _ - * @category Utility - * @param {number} n The number of times to invoke `iteratee`. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [thisArg] The `this` binding of `iteratee`. - * @returns {Array} Returns the array of results. - * @example - * - * var diceRolls = _.times(3, _.partial(_.random, 1, 6, false)); - * // => [3, 6, 4] - * - * _.times(3, function(n) { - * mage.castSpell(n); - * }); - * // => invokes `mage.castSpell(n)` three times with `n` of `0`, `1`, and `2` - * - * _.times(3, function(n) { - * this.cast(n); - * }, mage); - * // => also invokes `mage.castSpell(n)` three times - */ -function times(n, iteratee, thisArg) { - n = nativeFloor(n); - - // Exit early to avoid a JSC JIT bug in Safari 8 - // where `Array(0)` is treated as `Array(1)`. - if (n < 1 || !nativeIsFinite(n)) { - return []; - } - var index = -1, - result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); - - iteratee = bindCallback(iteratee, thisArg, 1); - while (++index < n) { - if (index < MAX_ARRAY_LENGTH) { - result[index] = iteratee(index); - } else { - iteratee(index); - } - } - return result; -} - -export default times; diff --git a/value.js b/value.js new file mode 100644 index 000000000..bca71bc8e --- /dev/null +++ b/value.js @@ -0,0 +1 @@ +export { default } from './wrapperValue' diff --git a/valueOf.js b/valueOf.js new file mode 100644 index 000000000..bca71bc8e --- /dev/null +++ b/valueOf.js @@ -0,0 +1 @@ +export { default } from './wrapperValue' diff --git a/object/values.js b/values.js similarity index 84% rename from object/values.js rename to values.js index a1c7d6287..b1525e329 100644 --- a/object/values.js +++ b/values.js @@ -1,4 +1,4 @@ -import baseValues from '../internal/baseValues'; +import baseValues from './internal/baseValues'; import keys from './keys'; /** @@ -27,7 +27,7 @@ import keys from './keys'; * // => ['h', 'i'] */ function values(object) { - return baseValues(object, keys(object)); + return object ? baseValues(object, keys(object)) : []; } export default values; diff --git a/object/valuesIn.js b/valuesIn.js similarity index 80% rename from object/valuesIn.js rename to valuesIn.js index c766fd062..3cea6d2ae 100644 --- a/object/valuesIn.js +++ b/valuesIn.js @@ -1,9 +1,8 @@ -import baseValues from '../internal/baseValues'; +import baseValues from './internal/baseValues'; import keysIn from './keysIn'; /** - * Creates an array of the own and inherited enumerable property values - * of `object`. + * Creates an array of the own and inherited enumerable property values of `object`. * * **Note:** Non-object values are coerced to objects. * @@ -25,7 +24,7 @@ import keysIn from './keysIn'; * // => [1, 2, 3] (iteration order is not guaranteed) */ function valuesIn(object) { - return baseValues(object, keysIn(object)); + return object == null ? baseValues(object, keysIn(object)) : []; } export default valuesIn; diff --git a/array/without.js b/without.js similarity index 69% rename from array/without.js rename to without.js index e49135fa9..1f67bbb62 100644 --- a/array/without.js +++ b/without.js @@ -1,6 +1,6 @@ -import baseDifference from '../internal/baseDifference'; -import isArrayLike from '../internal/isArrayLike'; -import restParam from '../function/restParam'; +import baseDifference from './internal/baseDifference'; +import isArrayLikeObject from './isArrayLikeObject'; +import rest from './rest'; /** * Creates an array excluding all provided values using @@ -18,8 +18,8 @@ import restParam from '../function/restParam'; * _.without([1, 2, 1, 3], 1, 2); * // => [3] */ -var without = restParam(function(array, values) { - return isArrayLike(array) +var without = rest(function(array, values) { + return isArrayLikeObject(array) ? baseDifference(array, values) : []; }); diff --git a/words.js b/words.js new file mode 100644 index 000000000..f7e6ad6c7 --- /dev/null +++ b/words.js @@ -0,0 +1,80 @@ +import toString from './toString'; + +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsQuoteRange = '\\u2018\\u2019\\u201c\\u201d', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsQuoteRange + rsSpaceRange; + +/** Used to compose unicode capture groups. */ +var rsBreak = '[' + rsBreakRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', + rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq; + +/** Used to match non-compound words composed of alphanumeric characters. */ +var reBasicWord = /[a-zA-Z0-9]+/g; + +/** Used to match complex or compound words. */ +var reComplexWord = RegExp([ + rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', + rsUpper + '?' + rsLowerMisc + '+', + rsDigits + '(?:' + rsLowerMisc + '+)?', + rsEmoji +].join('|'), 'g'); + +/** Used to detect strings that need a more robust regexp to match words. */ +var reHasComplexWord = /[a-z][A-Z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + +/** + * Splits `string` into an array of its words. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to inspect. + * @param {RegExp|string} [pattern] The pattern to match words. + * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`. + * @returns {Array} Returns the words of `string`. + * @example + * + * _.words('fred, barney, & pebbles'); + * // => ['fred', 'barney', 'pebbles'] + * + * _.words('fred, barney, & pebbles', /[^, ]+/g); + * // => ['fred', 'barney', '&', 'pebbles'] + */ +function words(string, pattern, guard) { + string = toString(string); + pattern = guard ? undefined : pattern; + + if (pattern === undefined) { + pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord; + } + return string.match(pattern) || []; +} + +export default words; diff --git a/function/wrap.js b/wrap.js similarity index 75% rename from function/wrap.js rename to wrap.js index 92a1b6237..317ba6cbb 100644 --- a/function/wrap.js +++ b/wrap.js @@ -1,8 +1,5 @@ -import createWrapper from '../internal/createWrapper'; -import identity from '../utility/identity'; - -/** Used to compose bitmasks for wrapper metadata. */ -var PARTIAL_FLAG = 32; +import identity from './identity'; +import partial from './partial'; /** * Creates a function that provides `value` to the wrapper function as its @@ -27,7 +24,7 @@ var PARTIAL_FLAG = 32; */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; - return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []); + return partial(wrapper, value); } export default wrap; diff --git a/wrapperAt.js b/wrapperAt.js new file mode 100644 index 000000000..c86f84f8d --- /dev/null +++ b/wrapperAt.js @@ -0,0 +1,48 @@ +import LazyWrapper from './internal/LazyWrapper'; +import LodashWrapper from './internal/LodashWrapper'; +import baseAt from './internal/baseAt'; +import baseFlatten from './internal/baseFlatten'; +import isIndex from './internal/isIndex'; +import rest from './rest'; +import thru from './thru'; + +/** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @category Seq + * @param {...(string|string[])} [paths] The property paths of elements to pick, + * specified individually or in arrays. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + * + * _(['a', 'b', 'c']).at(0, 2).value(); + * // => ['a', 'c'] + */ +var wrapperAt = rest(function(paths) { + paths = baseFlatten(paths); + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); +}); + +export default wrapperAt; diff --git a/chain/wrapperChain.js b/wrapperChain.js similarity index 88% rename from chain/wrapperChain.js rename to wrapperChain.js index 41568a312..ff5bf8cfb 100644 --- a/chain/wrapperChain.js +++ b/wrapperChain.js @@ -5,7 +5,7 @@ import chain from './chain'; * * @name chain * @memberOf _ - * @category Chain + * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example * @@ -15,12 +15,13 @@ import chain from './chain'; * ]; * * // without explicit chaining - * _(users).first(); + * _(users).head(); * // => { 'user': 'barney', 'age': 36 } * * // with explicit chaining - * _(users).chain() - * .first() + * _(users) + * .chain() + * .head() * .pick('user') * .value(); * // => { 'user': 'barney' } diff --git a/wrapperFlatMap.js b/wrapperFlatMap.js new file mode 100644 index 000000000..0dd9eaa8d --- /dev/null +++ b/wrapperFlatMap.js @@ -0,0 +1,22 @@ +/** + * This method is the wrapper version of `_.flatMap`. + * + * @static + * @memberOf _ + * @category Seq + * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _([1, 2]).flatMap(duplicate).value(); + * // => [1, 1, 2, 2] + */ +function wrapperFlatMap(iteratee) { + return this.map(iteratee).flatten(); +} + +export default wrapperFlatMap; diff --git a/wrapperLodash.js b/wrapperLodash.js new file mode 100644 index 000000000..90b91678e --- /dev/null +++ b/wrapperLodash.js @@ -0,0 +1,139 @@ +import LazyWrapper from './internal/LazyWrapper'; +import LodashWrapper from './internal/LodashWrapper'; +import baseLodash from './internal/baseLodash'; +import isArray from './isArray'; +import isObjectLike from './isObjectLike'; +import wrapperClone from './internal/wrapperClone'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chaining. Methods that operate on and return arrays, collections, and + * functions can be chained together. Methods that retrieve a single value or + * may return a primitive value will automatically end the chain sequence and + * return the unwrapped value. Otherwise, the value must be unwrapped with + * `_#value`. + * + * Explicit chaining, which must be unwrapped with `_#value` in all cases, + * may be enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. Shortcut + * fusion is an optimization to merge iteratee calls; this avoids the creation + * of intermediate arrays and can greatly reduce the number of iteratee executions. + * Sections of a chain sequence qualify for shortcut fusion if the section is + * applied to an array of at least two hundred elements and any iteratees + * accept only one argument. The heuristic for whether a section qualifies + * for shortcut fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, + * `at`, `before`, `bind`, `bindAll`, `bindKey`, `chain`, `chunk`, `commit`, + * `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, `curry`, + * `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`, + * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`, + * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flip`, `flow`, + * `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, + * `forOwnRight`, `fromPairs`, `functions`, `functionsIn`, `groupBy`, `initial`, + * `intersection`, `intersectionBy`, `intersectionWith`, invert`, `invokeMap`, + * `iteratee`, `keyBy`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, + * `matches`, `matchesProperty`, `memoize`, `merge`, `mergeWith`, `method`, + * `methodOf`, `mixin`, `negate`, `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, + * `over`, `overArgs`, `overEvery`, `overSome`, `partial`, `partialRight`, + * `partition`, `pick`, `pickBy`, `plant`, `property`, `propertyOf`, `pull`, + * `pullAll`, `pullAllBy`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, + * `reject`, `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, + * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, + * `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, + * `toArray`, `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, + * `unary`, `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, + * `unset`, `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `without`, + * `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, `zipObject`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `endsWith`, `eq`, + * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `floor`, `get`, `gt`, `gte`, + * `has`, `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, + * `invoke`, `isArguments`, `isArray`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`, + * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMatch`, + * `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`, + * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`, + * `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, `last`, + * `lastIndexOf`, `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, + * `mean`, `min`, `minBy`, `noConflict`, `noop`, `now`, `pad`, `padEnd`, + * `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, + * `result`, `round`, `runInContext`, `sample`, `shift`, `size`, `snakeCase`, + * `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, `sortedLastIndexBy`, + * `startCase`, `startsWith`, `subtract`, `sum`, sumBy`, `template`, `times`, + * `toLower`, `toInteger`, `toLength`, `toNumber`, `toSafeInteger`, toString`, + * `toUpper`, `trim`, `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, + * `upperCase`, `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // returns an unwrapped value + * wrapped.reduce(_.add); + * // => 6 + * + * // returns a wrapped value + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ +function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); +} + +// Ensure wrappers are instances of `baseLodash`. +lodash.prototype = baseLodash.prototype; + +export default lodash; diff --git a/chain/wrapperReverse.js b/wrapperReverse.js similarity index 52% rename from chain/wrapperReverse.js rename to wrapperReverse.js index 124965afb..6915c6e39 100644 --- a/chain/wrapperReverse.js +++ b/wrapperReverse.js @@ -1,17 +1,17 @@ -import LazyWrapper from '../internal/LazyWrapper'; -import LodashWrapper from '../internal/LodashWrapper'; +import LazyWrapper from './internal/LazyWrapper'; +import LodashWrapper from './internal/LodashWrapper'; +import reverse from './reverse'; import thru from './thru'; /** - * Reverses the wrapped array so the first element becomes the last, the - * second element becomes the second to last, and so on. + * This method is the wrapper version of `_.reverse`. * * **Note:** This method mutates the wrapped array. * * @name reverse * @memberOf _ - * @category Chain - * @returns {Object} Returns the new reversed `lodash` wrapper instance. + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var array = [1, 2, 3]; @@ -24,20 +24,16 @@ import thru from './thru'; */ function wrapperReverse() { var value = this.__wrapped__; - - var interceptor = function(value) { - return value.reverse(); - }; if (value instanceof LazyWrapper) { var wrapped = value; if (this.__actions__.length) { wrapped = new LazyWrapper(this); } wrapped = wrapped.reverse(); - wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + wrapped.__actions__.push({ 'func': thru, 'args': [reverse], 'thisArg': undefined }); return new LodashWrapper(wrapped, this.__chain__); } - return this.thru(interceptor); + return this.thru(reverse); } export default wrapperReverse; diff --git a/chain/wrapperValue.js b/wrapperValue.js similarity index 82% rename from chain/wrapperValue.js rename to wrapperValue.js index 59662bb79..47102c789 100644 --- a/chain/wrapperValue.js +++ b/wrapperValue.js @@ -1,4 +1,4 @@ -import baseWrapperValue from '../internal/baseWrapperValue'; +import baseWrapperValue from './internal/baseWrapperValue'; /** * Executes the chained sequence to extract the unwrapped value. @@ -6,7 +6,7 @@ import baseWrapperValue from '../internal/baseWrapperValue'; * @name value * @memberOf _ * @alias run, toJSON, valueOf - * @category Chain + * @category Seq * @returns {*} Returns the resolved unwrapped value. * @example * diff --git a/xor.js b/xor.js new file mode 100644 index 000000000..82672e7c5 --- /dev/null +++ b/xor.js @@ -0,0 +1,24 @@ +import arrayFilter from './internal/arrayFilter'; +import baseXor from './internal/baseXor'; +import isArrayLikeObject from './isArrayLikeObject'; +import rest from './rest'; + +/** + * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the provided arrays. + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of values. + * @example + * + * _.xor([2, 1], [4, 2]); + * // => [1, 4] + */ +var xor = rest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); +}); + +export default xor; diff --git a/xorBy.js b/xorBy.js new file mode 100644 index 000000000..d0667208f --- /dev/null +++ b/xorBy.js @@ -0,0 +1,36 @@ +import arrayFilter from './internal/arrayFilter'; +import baseIteratee from './internal/baseIteratee'; +import baseXor from './internal/baseXor'; +import isArrayLikeObject from './isArrayLikeObject'; +import last from './last'; +import rest from './rest'; + +/** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by which + * uniqueness is computed. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of values. + * @example + * + * _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor); + * // => [1.2, 4.3] + * + * // using the `_.property` iteratee shorthand + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ +var xorBy = rest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), baseIteratee(iteratee)); +}); + +export default xorBy; diff --git a/xorWith.js b/xorWith.js new file mode 100644 index 000000000..ea66c8fb0 --- /dev/null +++ b/xorWith.js @@ -0,0 +1,34 @@ +import arrayFilter from './internal/arrayFilter'; +import baseXor from './internal/baseXor'; +import isArrayLikeObject from './isArrayLikeObject'; +import last from './last'; +import rest from './rest'; + +/** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The comparator is invoked with + * two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ +var xorWith = rest(function(arrays) { + var comparator = last(arrays); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); +}); + +export default xorWith; diff --git a/array/zip.js b/zip.js similarity index 87% rename from array/zip.js rename to zip.js index 6a54d801d..90ee40fca 100644 --- a/array/zip.js +++ b/zip.js @@ -1,4 +1,4 @@ -import restParam from '../function/restParam'; +import rest from './rest'; import unzip from './unzip'; /** @@ -16,6 +16,6 @@ import unzip from './unzip'; * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] */ -var zip = restParam(unzip); +var zip = rest(unzip); export default zip; diff --git a/zipObject.js b/zipObject.js new file mode 100644 index 000000000..98dc1d7c7 --- /dev/null +++ b/zipObject.js @@ -0,0 +1,30 @@ +import baseSet from './internal/baseSet'; + +/** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property names and one of corresponding values. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} [props=[]] The property names. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['fred', 'barney'], [30, 40]); + * // => { 'fred': 30, 'barney': 40 } + */ +function zipObject(props, values) { + var index = -1, + length = props ? props.length : 0, + valsLength = values ? values.length : 0, + result = {}; + + while (++index < length) { + baseSet(result, props[index], index < valsLength ? values[index] : undefined); + } + return result; +} + +export default zipObject; diff --git a/zipWith.js b/zipWith.js new file mode 100644 index 000000000..36eda1a9e --- /dev/null +++ b/zipWith.js @@ -0,0 +1,30 @@ +import rest from './rest'; +import unzipWith from './unzipWith'; + +/** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ +var zipWith = rest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); +}); + +export default zipWith;