diff --git a/README.md b/README.md index b2fcee4fb..38ee8c6af 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# lodash v4.0.0 +# lodash v4.0.1 The [lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules. @@ -11,24 +11,26 @@ $ lodash -d -o ./lodash.js ## Installation Using npm: - ```bash $ {sudo -H} npm i -g npm $ npm i --save lodash ``` In Node.js: - ```js -// load the modern build +// load the full build var _ = require('lodash'); +// load the core build +var _ = require('lodash/core'); +// load the fp build +var _ = require('lodash/fp'); // or a method category var array = require('lodash/array'); // or a method (great for smaller builds with browserify/webpack) var chunk = require('lodash/chunk'); ``` -See the [package source](https://github.com/lodash/lodash/tree/4.0.0-npm) for more details. +See the [package source](https://github.com/lodash/lodash/tree/4.0.1-npm) for more details. **Note:**
Don’t assign values to the [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL.
@@ -36,7 +38,7 @@ Install [n_](https://www.npmjs.com/package/n_) for a REPL that includes lodash b ## Module formats -lodash is also available in a variety of other builds & module formats. +Lodash is also available in a variety of other builds & module formats. * [lodash](https://www.npmjs.com/package/lodash) & [per method](https://www.npmjs.com/browse/keyword/lodash-modularized) packages * [lodash-amd](https://www.npmjs.com/package/lodash-amd) @@ -52,5 +54,5 @@ lodash is also available in a variety of other builds & module formats. ## Support -Tested in Chrome 46-47, Firefox 42-43, IE 9-11, Edge 13, Safari 8-9, Node.js 0.10.x, 0.12.x, 4.x, & 5.x, & PhantomJS 1.9.8. +Tested in Chrome 46-47, Firefox 42-43, IE 9-11, Edge 13, Safari 8-9, Node.js 0.10.x, 0.12.x, 4.x, & 5.x, & PhantomJS 1.9.8. Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available. Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing. diff --git a/assignInWith.js b/assignInWith.js index 50c80f174..81a71b181 100644 --- a/assignInWith.js +++ b/assignInWith.js @@ -29,7 +29,7 @@ var copyObjectWith = require('./internal/copyObjectWith'), * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); * // => { 'a': 1, 'b': 2 } */ -var assignInWith = createAssigner(function(object, source, customizer) { +var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { copyObjectWith(source, keysIn(source), object, customizer); }); diff --git a/assignWith.js b/assignWith.js index 0e2eb96c1..8b32b89de 100644 --- a/assignWith.js +++ b/assignWith.js @@ -28,7 +28,7 @@ var copyObjectWith = require('./internal/copyObjectWith'), * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); * // => { 'a': 1, 'b': 2 } */ -var assignWith = createAssigner(function(object, source, customizer) { +var assignWith = createAssigner(function(object, source, srcIndex, customizer) { copyObjectWith(source, keys(source), object, customizer); }); diff --git a/cloneDeepWith.js b/cloneDeepWith.js index a306cfc32..c814cf50f 100644 --- a/cloneDeepWith.js +++ b/cloneDeepWith.js @@ -17,7 +17,7 @@ var baseClone = require('./internal/baseClone'); * } * } * - * var el = _.cloneDeep(document.body, customizer); + * var el = _.cloneDeepWith(document.body, customizer); * * console.log(el === document.body); * // => false diff --git a/cloneWith.js b/cloneWith.js index fdd6b063c..e436b1e8c 100644 --- a/cloneWith.js +++ b/cloneWith.js @@ -4,7 +4,7 @@ var baseClone = require('./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]). + * up to four arguments; (value [, index|key, object, stack]). * * @static * @memberOf _ @@ -20,7 +20,7 @@ var baseClone = require('./internal/baseClone'); * } * } * - * var el = _.clone(document.body, customizer); + * var el = _.cloneWith(document.body, customizer); * * console.log(el === document.body); * // => false diff --git a/concat.js b/concat.js index b023ca447..ecee6f893 100644 --- a/concat.js +++ b/concat.js @@ -25,8 +25,11 @@ var arrayConcat = require('./internal/arrayConcat'), * // => [1] */ var concat = rest(function(array, values) { + if (!isArray(array)) { + array = array == null ? [] : [Object(array)]; + } values = baseFlatten(values); - return arrayConcat(isArray(array) ? array : [Object(array)], values); + return arrayConcat(array, values); }); module.exports = concat; diff --git a/cond.js b/cond.js index 99d40eaf6..d04cfd909 100644 --- a/cond.js +++ b/cond.js @@ -23,7 +23,7 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * [_.matches({ 'a': 1 }), _.constant('matches A')], * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], * [_.constant(true), _.constant('no match')] - * ]) + * ]); * * func({ 'a': 1, 'b': 2 }); * // => 'matches A' diff --git a/core.js b/core.js new file mode 100644 index 000000000..9aa3e4df8 --- /dev/null +++ b/core.js @@ -0,0 +1,3857 @@ +/** + * @license + * lodash 4.0.1 (Custom Build) + * Build: `lodash core -o ./dist/lodash.core.js` + * 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 + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.0.1'; + + /** Used to compose bitmasks for wrapper metadata. */ + var BIND_FLAG = 1, + PARTIAL_FLAG = 32; + + /** Used to compose bitmasks for comparison styles. */ + var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; + + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used as references for various `Number` constants. */ + var MAX_SAFE_INTEGER = 9007199254740991; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + stringTag = '[object String]'; + + /** Used to match HTML entities and HTML characters. */ + var reUnescapedHtml = /[&<>"'`]/g, + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + + /** Used to determine if values are of the language type `Object`. */ + var objectTypes = { + 'function': true, + 'object': true + }; + + /** Detect free variable `exports`. */ + var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null; + + /** Detect free variable `module`. */ + var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + + /** Detect free variable `self`. */ + var freeSelf = checkGlobal(objectTypes[typeof self] && self); + + /** Detect free variable `window`. */ + var freeWindow = checkGlobal(objectTypes[typeof window] && window); + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : null; + + /** Detect `this` as the global object. */ + var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + + /** + * Used as a reference to the global object. + * + * 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 !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')(); + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a new array concatenating `array` with `other`. + * + * @private + * @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) { + return arrayPush(copyArray(array), values); + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @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(array, iteratee, comparator) { + var index = -1, + length = array.length; + + 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; + } + + /** + * The base implementation of methods like `_.find` and `_.findKey`, without + * support for iteratee shorthands, which iterates over `collection` using + * `eachFunc`. + * + * @private + * @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. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum 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. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * 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; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values 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 array of property values. + */ + function baseValues(object, props) { + return baseMap(props, function(key) { + return object[key]; + }); + } + + /** + * 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; + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + 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; + } + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + + /** + * 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; + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + + /** + * 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; + } + + /*--------------------------------------------------------------------------*/ + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** + * 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 restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Built-in value references. */ + var Reflect = root.Reflect, + Symbol = root.Symbol, + Uint8Array = root.Uint8Array, + enumerate = Reflect ? Reflect.enumerate : undefined, + propertyIsEnumerable = objectProto.propertyIsEnumerable; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeIsFinite = root.isFinite, + nativeKeys = Object.keys, + nativeMax = Math.max; + + /*------------------------------------------------------------------------*/ + + /** + * 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`, `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`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `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)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable chaining for all wrapper methods. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + } + + /*------------------------------------------------------------------------*/ + + /** + * 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; + } + + /** + * 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; + } + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} prototype The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object; + object.prototype = undefined; + } + return result || {}; + }; + }()); + + /** + * The base implementation of `_.delay` and `_.defer` which accepts an array + * of `func` arguments. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Object} args The arguments provide to `func`. + * @returns {number} Returns the timer id. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @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` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {boolean} [isDeep] Specify a deep flatten. + * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index]; + if (isArrayLikeObject(value) && + (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForIn` and `baseForOwn` which iterates + * over `object` properties returned by `keysFunc` invoking `iteratee` for + * each property. Iteratee functions may exit iteration early by explicitly + * returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. + */ + function baseFunctions(object, props) { + return baseFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * 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 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, 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, bitmask, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @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 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, bitmask, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = arrayTag, + othTag = arrayTag; + + if (!objIsArr) { + objTag = objectToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } + } + if (!othIsArr) { + othTag = objectToString.call(other); + if (othTag == argsTag) { + 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, equalFunc, customizer, bitmask); + } + 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, bitmask, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = []); + var stacked = find(stack, function(entry) { + return entry[0] === object; + }); + if (stacked && stacked[1]) { + return stacked[1] == other; + } + stack.push([object, other]); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack); + stack.pop(); + return result; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(func) { + var type = typeof func; + if (type == 'function') { + return func; + } + return func == null + ? identity + : (type == 'object' ? baseMatches : baseProperty)(func); + } + + /** + * 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)); + } + + /** + * 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)); + }; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new function. + */ + function baseMatches(source) { + var props = keys(source); + return function(object) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length]; + if (!(key in object && + baseIsEqual(source[key], object[key], undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG) + )) { + return false; + } + } + return true; + }; + } + + /** + * 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 reduce(props, function(result, key) { + if (key in object) { + result[key] = object[key]; + } + return result; + }, {}); + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source) { + return baseSlice(source, 0, source.length); + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @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`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + return reduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * Copies properties of `source` to `object`. + * + * @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. + * @returns {Object} Returns `object`. + */ + var copyObject = copyObjectWith; + + /** + * 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; + } + + /** + * 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 rest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined; + + customizer = typeof customizer == 'function' ? (length--, customizer) : undefined; + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtorWrapper(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. + // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * 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 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 wrapped function. + */ + function createPartialWrapper(func, bitmask, thisArg, partials) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var isBind = bitmask & BIND_FLAG, + Ctor = createCtorWrapper(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @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 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, bitmask, stack) { + var index = -1, + isPartial = bitmask & PARTIAL_COMPARE_FLAG, + isUnordered = bitmask & UNORDERED_COMPARE_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + var result = true; + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + var compared; + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (isUnordered) { + if (!baseSome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack); + })) { + result = false; + break; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { + result = false; + break; + } + } + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @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, equalFunc, customizer, bitmask) { + switch (tag) { + + case boolTag: + case dateTag: + // Coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + // Treat `NaN` vs. `NaN` as equal. + 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 + ''); + + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @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 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, bitmask, stack) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG, + objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var result = true; + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + var compared; + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + return result; + } + + /** + * Gets the "length" property value of `object`. + * + * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) + * that affects Safari on at least iOS 8.1-8.3 ARM64. + * + * @private + * @param {Object} object The object to query. + * @returns {*} Returns the "length" value. + */ + var getLength = baseProperty('length'); + + /** + * 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; + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + return baseFilter(array, Boolean); + } + + /** + * 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) { + if (!isArray(array)) { + array = array == null ? [] : [Object(array)]; + } + values = baseFlatten(values); + return arrayConcat(array, values); + }); + + /** + * 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) : []; + } + + /** + * This method is like `_.flatten` except that it recursively flattens `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to recursively flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, 3, [4]]]); + * // => [1, 2, 3, 4] + */ + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return array ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * 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 `array`. If `array` is sorted providing `true` for `fromIndex` + * performs a faster binary search. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // using `fromIndex` + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else { + fromIndex = 0; + } + var index = (fromIndex || 0) - 1, + isReflexive = value === value; + + while (++index < length) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { + return index; + } + } + return -1; + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of [`Array#slice`](https://mdn.io/Array/slice) + * to ensure dense arrays are returned. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array ? array.length : 0; + start = start == null ? 0 : +start; + end = end === undefined ? length : +end; + return length ? baseSlice(array, start, end) : []; + } + + /*------------------------------------------------------------------------*/ + + /** + * 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; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor is + * 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 Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * + * @static + * @memberOf _ + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * Enables explicit method chaining on the wrapper object. + * + * @name chain + * @memberOf _ + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // without explicit chaining + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // with explicit chaining + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chained sequence to extract the unwrapped value. + * + * @name value + * @memberOf _ + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * 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) { + predicate = guard ? undefined : predicate; + return baseEvery(collection, baseIteratee(predicate)); + } + + /** + * 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) { + return baseFilter(collection, baseIteratee(predicate)); + } + + /** + * 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) { + return baseFind(collection, baseIteratee(predicate), baseEach); + } + + /** + * 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 baseEach(collection, toFunction(iteratee)); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `methodName` is a function it's + * invoked for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @category Collection + * @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 each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = rest(function(collection, path, args) { + var isFunc = typeof path == 'function'; + return baseMap(collection, function(value) { + var func = isFunc ? path : value[path]; + return func == null ? func : func.apply(value, args); + }); + }); + + /** + * 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([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (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) { + return baseMap(collection, baseIteratee(iteratee)); + } + + /** + * 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) { + return baseReduce(collection, baseIteratee(iteratee), accumulator, arguments.length < 3, baseEach); + } + + /** + * 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; + } + collection = isArrayLike(collection) ? collection : keys(collection); + return collection.length; + } + + /** + * 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) { + predicate = guard ? undefined : predicate; + return baseSome(collection, baseIteratee(predicate)); + } + + /** + * 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]] + */ + function sortBy(collection, iteratee) { + var index = 0; + iteratee = baseIteratee(iteratee); + + return baseMap(baseMap(collection, function(value, key, collection) { + return { 'value': value, 'index': index++, 'criteria': iteratee(value, key, collection) }; + }).sort(function(object, other) { + return compareAscending(object.criteria, other.criteria) || (object.index - other.index); + }), baseProperty('value')); + } + + /*------------------------------------------------------------------------*/ + + /** + * 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; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * 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') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and prepends any additional `_.bind` arguments to those provided to the + * bound function. + * + * 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 doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var greet = function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * }; + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // using placeholders + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = rest(function(func, thisArg, partials) { + return createPartialWrapper(func, BIND_FLAG | PARTIAL_FLAG, thisArg, partials); + }); + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // logs 'deferred' after one or more milliseconds + */ + var defer = rest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @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 `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => logs 'later' after one second + */ + var delay = rest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * 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 _ + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` invokes `createApplication` once + */ + function once(func) { + return before(2, func); + } + + /** + * 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://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = array; + return func.apply(this, otherArgs); + }; + } + + /*------------------------------------------------------------------------*/ + + /** + * 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) { + if (!isObject(value)) { + return value; + } + return isArray(value) ? copyArray(value) : copyObject(value, keys(value)); + } + + /** + * 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); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`. + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + function gt(value, other) { + return value > other; + } + + /** + * 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); + } + + /** + * 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; + + /** + * 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)); + } + + /** + * 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); + } + + /** + * Checks if `value` is classified as a boolean 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 + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && objectToString.call(value) == boolTag); + } + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + function isDate(value) { + return isObjectLike(value) && objectToString.call(value) == dateTag; + } + + /** + * Checks if `value` is empty. A value is considered empty unless it's an + * `arguments` object, array, string, or jQuery-like collection with a length + * greater than `0` or an object with own enumerable properties. + * + * @static + * @memberOf _ + * @category Lang + * @param {Array|Object|string} value The value to inspect. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + return (!isObjectLike(value) || isFunction(value.splice)) + ? !size(value) + : !keys(value).length; + } + + /** + * 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); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MAX_VALUE); + * // => true + * + * _.isFinite(3.14); + * // => true + * + * _.isFinite(Infinity); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // 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; + } + + /** + * 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; + } + + /** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); + } + + /** + * 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'; + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4) + * which returns `true` for `undefined` and other non-numeric values. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + 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 ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && objectToString.call(value) == numberTag); + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + function isRegExp(value) { + return isObject(value) && objectToString.call(value) == regexpTag; + } + + /** + * Checks if `value` is classified as a `String` 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 + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); + } + + /** + * Checks if `value` is `undefined`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`. + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + function lt(value, other) { + return value < other; + } + + /** + * 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 (!isArrayLike(value)) { + return values(value); + } + return value.length ? copyArray(value) : []; + } + + /** + * 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 + */ + var toInteger = Number; + + /** + * 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 + */ + var toNumber = Number; + + /** + * 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) { + if (typeof value == 'string') { + return value; + } + return value == null ? '' : (value + ''); + } + + /*------------------------------------------------------------------------*/ + + /** + * 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); + }); + + /** + * 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); + }); + + /** + * 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, srcIndex, customizer) { + copyObjectWith(source, keysIn(source), object, customizer); + }); + + /** + * 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. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties ? assign(result, properties) : result; + } + + /** + * 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 assignInWith.apply(undefined, args); + }); + + /** + * 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 object != null && hasOwnProperty.call(object, path); + } + + /** + * 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 (hasOwnProperty.call(object, key) && + !(skipIndexes && (key == 'length' || isIndex(key, length))) && + !(isProto && key == 'constructor')) { + result.push(key); + } + } + return result; + } + + /** + * 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; + } + + /** + * 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)); + }); + + /** + * This method is like `_.get` except that if the resolved value is a function + * it's invoked with the `this` binding of its parent object and its result + * is returned. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned if the resolved value is `undefined`. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + var value = object == null ? undefined : object[path]; + if (value === undefined) { + value = defaultValue; + } + return isFunction(value) ? value.call(object) : value; + } + + /** + * Creates an array of the own enumerable property values 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 values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object ? baseValues(object, keys(object)) : []; + } + + /*------------------------------------------------------------------------*/ + + /** + * 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). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. + * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * 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. + * + * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping) + * to reduce XSS vectors. + * + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /*------------------------------------------------------------------------*/ + + /** + * This method returns the first argument provided to it. + * + * @static + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'user': 'fred' }; + * + * _.identity(object) === object; + * // => true + */ + function identity(value) { + return value; + } + + /** + * 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 }] + */ + var iteratee = baseIteratee; + + /** + * 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(assign({}, source)); + } + + /** + * 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); + + if (options == null && + !(isObject(source) && (methodNames.length || !props.length))) { + options = source; + source = object; + object = this; + methodNames = baseFunctions(source, keys(source)); + } + var chain = (isObject(options) && 'chain' in options) ? options.chain : true, + isFunc = isFunction(object); + + baseEach(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; + } + + /** + * Reverts the `_` variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @memberOf _ + * @category Util + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + if (root._ === this) { + root._ = oldDash; + } + return this; + } + + /** + * A no-operation function that returns `undefined` regardless of the + * arguments it receives. + * + * @static + * @memberOf _ + * @category Util + * @example + * + * var object = { 'user': 'fred' }; + * + * _.noop(object) === undefined; + * // => true + */ + function noop() { + // No operation performed. + } + + /** + * Generates a unique ID. If `prefix` is provided the ID is appended to it. + * + * @static + * @memberOf _ + * @category Util + * @param {string} [prefix] The value to prefix the ID with. + * @returns {string} Returns the unique ID. + * @example + * + * _.uniqueId('contact_'); + * // => 'contact_104' + * + * _.uniqueId(); + * // => '105' + */ + function uniqueId(prefix) { + var id = ++idCounter; + return toString(prefix) + id; + } + + /*------------------------------------------------------------------------*/ + + /** + * 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; + } + + /** + * 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; + } + + /*------------------------------------------------------------------------*/ + + LodashWrapper.prototype = baseCreate(lodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + // Add functions that return wrapped values when chaining. + lodash.assignIn = assignIn; + lodash.before = before; + lodash.bind = bind; + lodash.chain = chain; + lodash.compact = compact; + lodash.concat = concat; + lodash.create = create; + lodash.defaults = defaults; + lodash.defer = defer; + lodash.delay = delay; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.invokeMap = invokeMap; + lodash.iteratee = iteratee; + lodash.keys = keys; + lodash.map = map; + lodash.matches = matches; + lodash.mixin = mixin; + lodash.negate = negate; + lodash.once = once; + lodash.pick = pick; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.tap = tap; + lodash.thru = thru; + lodash.toArray = toArray; + lodash.values = values; + + // Add aliases. + lodash.extend = assignIn; + + // Add functions to `lodash.prototype`. + mixin(lodash, lodash); + + /*------------------------------------------------------------------------*/ + + // Add functions that return unwrapped values when chaining. + lodash.clone = clone; + lodash.escape = escape; + lodash.every = every; + lodash.find = find; + lodash.forEach = forEach; + lodash.has = has; + lodash.head = head; + lodash.identity = identity; + lodash.indexOf = indexOf; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isNaN = isNaN; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isUndefined = isUndefined; + lodash.last = last; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.reduce = reduce; + lodash.result = result; + lodash.size = size; + lodash.some = some; + lodash.uniqueId = uniqueId; + + // Add aliases. + lodash.each = forEach; + lodash.first = 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; + + // Add `Array` and `String` methods to `lodash.prototype`. + baseEach(['pop', 'join', 'replace', 'reverse', 'split', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? String.prototype : arrayProto)[methodName], + chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', + retUnwrapped = /^(?:pop|join|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); + }); + }; + }); + + // Add chaining functions to the `lodash` wrapper. + lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + + /*--------------------------------------------------------------------------*/ + + // Expose lodash on the free variable `window` or `self` when available. This + // prevents errors in cases where lodash is loaded by a script tag in the presence + // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details. + (freeWindow || freeSelf || {})._ = lodash; + + // Some AMD build optimizers like r.js check for condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Define as an anonymous module so, through path mapping, it can be + // referenced as the "underscore" module. + define(function() { + return lodash; + }); + } + // Check for `exports` after `define` in case a build optimizer adds an `exports` object. + else if (freeExports && freeModule) { + // Export for Node.js. + if (moduleExports) { + (freeModule.exports = lodash)._ = lodash; + } + // Export for CommonJS support. + freeExports._ = lodash; + } + else { + // Export to the global object. + root._ = lodash; + } +}.call(this)); diff --git a/countBy.js b/countBy.js index c5ccdfde3..074544df0 100644 --- a/countBy.js +++ b/countBy.js @@ -16,7 +16,7 @@ var hasOwnProperty = objectProto.hasOwnProperty; * @memberOf _ * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * diff --git a/deburr.js b/deburr.js index 79bd9f278..944735a87 100644 --- a/deburr.js +++ b/deburr.js @@ -5,12 +5,16 @@ var deburrLetter = require('./internal/deburrLetter'), var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; /** Used to compose unicode character classes. */ -var rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23'; +var rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0'; /** Used to compose unicode capture groups. */ -var rsCombo = '[' + rsComboRange + ']'; +var rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']'; -/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ +/** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ var reComboMark = RegExp(rsCombo, 'g'); /** diff --git a/extend.js b/extend.js new file mode 100644 index 000000000..e00166c20 --- /dev/null +++ b/extend.js @@ -0,0 +1 @@ +module.exports = require('./assignIn'); diff --git a/extendWith.js b/extendWith.js new file mode 100644 index 000000000..dbdcb3b4e --- /dev/null +++ b/extendWith.js @@ -0,0 +1 @@ +module.exports = require('./assignInWith'); diff --git a/fp.js b/fp.js index d3b61a6d3..d8887e0fe 100644 --- a/fp.js +++ b/fp.js @@ -1 +1,2 @@ -module.exports = require('./fp/convert.js')(); +var _ = require('./lodash').noConflict().runInContext(); +module.exports = require('./fp/convert')(_); diff --git a/fp/baseConvert.js b/fp/_baseConvert.js similarity index 76% rename from fp/baseConvert.js rename to fp/_baseConvert.js index f43ee6240..10a7d70bc 100644 --- a/fp/baseConvert.js +++ b/fp/_baseConvert.js @@ -1,5 +1,6 @@ -var mapping = require('./mapping.js'), - mutateMap = mapping.mutateMap; +var mapping = require('./_mapping'), + mutateMap = mapping.mutate, + placeholder = {}; /** * The base implementation of `convert` which accepts a `util` object of methods @@ -39,21 +40,16 @@ function baseConvert(util, name, func) { keys = _.keys, rearg = _.rearg; - var baseAry = function(func, n) { - return function() { - var args = arguments, - length = Math.min(args.length, n); + var baseArity = function(func, n) { + return n == 2 + ? function(a, b) { return func.apply(undefined, arguments); } + : function(a) { return func.apply(undefined, arguments); }; + }; - switch (length) { - case 1: return func(args[0]); - case 2: return func(args[0], args[1]); - } - args = Array(length); - while (length--) { - args[length] = arguments[length]; - } - return func.apply(undefined, args); - }; + var baseAry = function(func, n) { + return n == 2 + ? function(a, b) { return func(a, b); } + : function(a) { return func(a); }; }; var cloneArray = function(array) { @@ -82,6 +78,13 @@ function baseConvert(util, name, func) { }); }; + var iterateeRearg = function(func, indexes) { + return overArg(func, function(func) { + var n = indexes.length; + return baseArity(rearg(baseAry(func, n), indexes), n); + }); + }; + var overArg = function(func, iteratee, retArg) { return function() { var length = arguments.length, @@ -98,7 +101,10 @@ function baseConvert(util, name, func) { var wrappers = { 'iteratee': function(iteratee) { - return function(func, arity) { + return function() { + var func = arguments[0], + arity = arguments[1]; + arity = arity > 2 ? (arity - 2) : 1; func = iteratee(func); var length = func.length; @@ -158,14 +164,18 @@ function baseConvert(util, name, func) { } var result; each(mapping.caps, function(cap) { - each(mapping.aryMethodMap[cap], function(otherName) { + each(mapping.aryMethod[cap], function(otherName) { if (name == otherName) { + var indexes = mapping.iterateeRearg[name], + n = !isLib && mapping.aryIteratee[name]; + result = ary(func, cap); - if (cap > 1 && !mapping.skipReargMap[name]) { - result = rearg(result, mapping.methodReargMap[name] || mapping.aryReargMap[cap]); + if (cap > 1 && !mapping.skipRearg[name]) { + result = rearg(result, mapping.methodRearg[name] || mapping.aryRearg[cap]); } - var n = !isLib && mapping.aryIterateeMap[name]; - if (n) { + if (indexes) { + result = iterateeRearg(result, indexes); + } else if (n) { result = iterateeAry(result, n); } if (cap > 1) { @@ -176,7 +186,12 @@ function baseConvert(util, name, func) { }); return !result; }); - return result || func; + + result || (result = func); + if (mapping.placeholder[name]) { + result.placeholder = placeholder; + } + return result; }; if (!isLib) { @@ -185,8 +200,8 @@ function baseConvert(util, name, func) { // Iterate over methods for the current ary cap. var pairs = []; each(mapping.caps, function(cap) { - each(mapping.aryMethodMap[cap], function(key) { - var func = _[mapping.keyMap[key] || key]; + each(mapping.aryMethod[cap], function(key) { + var func = _[mapping.key[key] || key]; if (func) { pairs.push([key, wrap(key, func)]); } @@ -200,7 +215,7 @@ function baseConvert(util, name, func) { // Wrap the lodash method and its aliases. each(keys(_), function(key) { - each(mapping.aliasMap[key] || [], function(alias) { + each(mapping.alias[key] || [], function(alias) { _[alias] = _[key]; }); }); diff --git a/fp/_convertBrowser.js b/fp/_convertBrowser.js new file mode 100644 index 000000000..b076778a4 --- /dev/null +++ b/fp/_convertBrowser.js @@ -0,0 +1,13 @@ +var baseConvert = require('./_baseConvert'); + +/** + * Converts `lodash` to an immutable auto-curried iteratee-first data-last version. + * + * @param {Function} lodash The lodash function. + * @returns {Function} Returns the converted `lodash`. + */ +function browserConvert(lodash) { + return baseConvert(lodash, lodash); +} + +module.exports = browserConvert; diff --git a/fp/_mapping.js b/fp/_mapping.js new file mode 100644 index 000000000..4f1e607ee --- /dev/null +++ b/fp/_mapping.js @@ -0,0 +1,202 @@ +module.exports = { + + /** Used to map method names to their aliases. */ + 'alias': { + 'ary': ['nAry'], + 'assignIn': ['extend'], + 'assignInWith': ['extendWith'], + 'filter': ['whereEq'], + 'flatten': ['unnest'], + 'flow': ['pipe'], + 'flowRight': ['compose'], + 'forEach': ['each'], + 'forEachRight': ['eachRight'], + 'get': ['path', 'prop'], + 'getOr': ['pathOr', 'propOr'], + 'head': ['first'], + 'includes': ['contains'], + 'initial': ['init'], + 'isEqual': ['equals'], + 'mapValues': ['mapObj'], + 'matchesProperty': ['pathEq'], + 'omit': ['dissoc', 'omitAll'], + 'overArgs': ['useWith'], + 'overEvery': ['allPass'], + 'overSome': ['somePass'], + 'pick': ['pickAll'], + 'propertyOf': ['propOf'], + 'rest': ['unapply'], + 'some': ['all'], + 'spread': ['apply'], + 'zipObject': ['zipObj'] + }, + + /** Used to map method names to their iteratee ary. */ + 'aryIteratee': { + 'assignWith': 2, + 'assignInWith': 2, + 'cloneDeepWith': 1, + 'cloneWith': 1, + 'dropRightWhile': 1, + 'dropWhile': 1, + 'every': 1, + 'filter': 1, + 'find': 1, + 'findIndex': 1, + 'findKey': 1, + 'findLast': 1, + 'findLastIndex': 1, + 'findLastKey': 1, + 'flatMap': 1, + 'forEach': 1, + 'forEachRight': 1, + 'forIn': 1, + 'forInRight': 1, + 'forOwn': 1, + 'forOwnRight': 1, + 'isEqualWith': 2, + 'isMatchWith': 2, + 'map': 1, + 'mapKeys': 1, + 'mapValues': 1, + 'partition': 1, + 'reduce': 2, + 'reduceRight': 2, + 'reject': 1, + 'remove': 1, + 'some': 1, + 'takeRightWhile': 1, + 'takeWhile': 1, + 'times': 1, + 'transform': 2 + }, + + /** Used to map ary to method names. */ + 'aryMethod': { + 1:[ + 'attempt', 'ceil', 'create', 'curry', 'curryRight', 'floor', 'fromPairs', + 'invert', 'iteratee', 'memoize', 'method', 'methodOf', 'mixin', 'over', + 'overEvery', 'overSome', 'rest', 'reverse', 'round', 'runInContext', + 'template', 'trim', 'trimEnd', 'trimStart', 'uniqueId', 'words' + ], + 2:[ + 'add', 'after', 'ary', 'assign', 'at', 'before', 'bind', 'bindKey', + 'chunk', 'cloneDeepWith', 'cloneWith', 'concat', 'countBy', 'curryN', + 'curryRightN', 'debounce', 'defaults', 'defaultsDeep', 'delay', 'difference', + 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq', + 'every', 'extend', 'filter', 'find', 'find', 'findIndex', 'findKey', + 'findLast', 'findLastIndex', 'findLastKey', 'flatMap', 'forEach', + 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get', + 'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection', + 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', 'lastIndexOf', + 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', 'maxBy', + 'merge', 'minBy', 'omit', 'omitBy', 'orderBy', 'overArgs', 'pad', 'padEnd', + 'padStart', 'parseInt', 'partition', 'pick', 'pickBy', 'pull', 'pullAll', + 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', + 'repeat', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', + 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', + 'split', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', 'takeRightWhile', + 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'truncate', 'union', 'uniqBy', + 'uniqWith', 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject' + ], + 3:[ + 'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', + 'getOr', 'inRange', 'intersectionBy', 'intersectionWith', 'isEqualWith', + 'isMatchWith', 'mergeWith', 'pullAllBy', 'reduce', 'reduceRight', 'replace', + 'set', 'slice', 'sortedIndexBy', 'sortedLastIndexBy', 'transform', 'unionBy', + 'unionWith', 'xorBy', 'xorWith', 'zipWith' + ], + 4:[ + 'fill', 'setWith' + ] + }, + + /** Used to map ary to rearg configs. */ + 'aryRearg': { + 2: [1, 0], + 3: [2, 1, 0], + 4: [3, 2, 0, 1] + }, + + /** Used to map method names to iteratee rearg configs. */ + 'iterateeRearg': { + 'findKey': [1], + 'findLastKey': [1], + 'mapKeys': [1] + }, + + /** Used to map method names to rearg configs. */ + 'methodRearg': { + 'clamp': [2, 0, 1], + 'reduce': [2, 0, 1], + 'reduceRight': [2, 0, 1], + 'set': [2, 0, 1], + 'setWith': [3, 1, 2, 0], + 'slice': [2, 0, 1], + 'transform': [2, 0, 1] + }, + + /** Used to iterate `mapping.aryMethod` keys. */ + 'caps': [1, 2, 3, 4], + + /** Used to map keys to other keys. */ + 'key': { + 'curryN': 'curry', + 'curryRightN': 'curryRight', + 'getOr': 'get' + }, + + /** Used to identify methods which mutate arrays or objects. */ + 'mutate': { + 'array': { + 'fill': true, + 'pull': true, + 'pullAll': true, + 'pullAllBy': true, + 'pullAt': true, + 'remove': true, + 'reverse': true + }, + 'object': { + 'assign': true, + 'assignIn': true, + 'assignInWith': true, + 'assignWith': true, + 'defaults': true, + 'defaultsDeep': true, + 'merge': true, + 'mergeWith': true + }, + 'set': { + 'set': true, + 'setWith': true + } + }, + + /** Used to track methods with placeholder support */ + 'placeholder': { + 'bind': true, + 'bindKey': true, + 'curry': true, + 'curryRight': true, + 'partial': true, + 'partialRight': true + }, + + /** Used to track methods that skip `_.rearg`. */ + 'skipRearg': { + 'assign': true, + 'assignIn': true, + 'concat': true, + 'defaults': true, + 'defaultsDeep': true, + 'difference': true, + 'matchesProperty': true, + 'merge': true, + 'random': true, + 'range': true, + 'rangeRight': true, + 'zip': true, + 'zipObject': true + } +}; diff --git a/fp/util.js b/fp/_util.js similarity index 100% rename from fp/util.js rename to fp/_util.js diff --git a/fp/convert.browser.js b/fp/convert.browser.js deleted file mode 100644 index 6855f34f8..000000000 --- a/fp/convert.browser.js +++ /dev/null @@ -1,13 +0,0 @@ -var baseConvert = require('./baseConvert.js'); - -/** - * Converts `lodash` to an auto-curried iteratee-first data-last version. - * - * @param {Function} lodash The lodash function. - * @returns {Function} Returns the converted lodash function. - */ -function browserConvert(lodash) { - return baseConvert(lodash, lodash); -} - -module.exports = browserConvert; diff --git a/fp/convert.js b/fp/convert.js index 49aca2b7f..85f3b7535 100644 --- a/fp/convert.js +++ b/fp/convert.js @@ -1,20 +1,15 @@ -var _ = require('../lodash'), - baseConvert = require('./baseConvert.js'), - util = require('./util.js'); +var baseConvert = require('./_baseConvert'), + util = require('./_util'); /** - * Converts `func` of `name` to an auto-curried iteratee-first data-last version. - * If `name` is an object, the methods on it will be converted and the object returned. + * Converts `func` of `name` to an immutable auto-curried iteratee-first data-last + * version. If `name` is an object its methods will be converted. * - * @param {string} [name] The name of the function to wrap. + * @param {string} name The name of the function to wrap. * @param {Function} [func] The function to wrap. * @returns {Function|Object} Returns the converted function or object. */ -function convert() { - var args = arguments, - name = args.length ? args[0] : _.noConflict().runInContext(), - func = args[1]; - +function convert(name, func) { return baseConvert(util, name, func); } diff --git a/fp/convert.node.js b/fp/convert.node.js deleted file mode 100644 index ef26d5cbf..000000000 --- a/fp/convert.node.js +++ /dev/null @@ -1,16 +0,0 @@ -var baseConvert = require('./baseConvert.js'), - util = require('./util.js'); - -/** - * Converts `func` of `name` to an auto-curried iteratee-first data-last version. - * If `name` is an object, the methods on it will be converted and the object returned. - * - * @param {string} name The name of the function to wrap. - * @param {Function} func The function to wrap. - * @returns {Function|Object} Returns the converted function or object. - */ -function nodeConvert(name, func) { - return baseConvert(util, name, func); -} - -module.exports = nodeConvert; diff --git a/fp/mapping.js b/fp/mapping.js deleted file mode 100644 index 4c76e4289..000000000 --- a/fp/mapping.js +++ /dev/null @@ -1,164 +0,0 @@ -module.exports = { - - /** Used to map method names to their aliases. */ - 'aliasMap': { - 'ary': ['nAry'], - 'overEvery': ['allPass'], - 'overSome': ['somePass'], - 'filter': ['whereEq'], - 'flatten': ['unnest'], - 'flow': ['pipe'], - 'flowRight': ['compose'], - 'forEach': ['each'], - 'forEachRight': ['eachRight'], - 'get': ['path'], - 'getOr': ['pathOr'], - 'head': ['first'], - 'includes': ['contains'], - 'initial': ['init'], - 'isEqual': ['equals'], - 'mapValues': ['mapObj'], - 'matchesProperty': ['pathEq'], - 'overArgs': ['useWith'], - 'omit': ['dissoc', 'omitAll'], - 'pick': ['pickAll'], - 'property': ['prop'], - 'propertyOf': ['propOf'], - 'rest': ['unapply'], - 'some': ['all'], - 'spread': ['apply'], - 'zipObject': ['zipObj'] - }, - - /** Used to map method names to their iteratee ary. */ - 'aryIterateeMap': { - 'assignWith': 2, - 'cloneDeepWith': 1, - 'cloneWith': 1, - 'dropRightWhile': 1, - 'dropWhile': 1, - 'every': 1, - 'extendWith': 2, - 'filter': 1, - 'find': 1, - 'findIndex': 1, - 'findKey': 1, - 'findLast': 1, - 'findLastIndex': 1, - 'findLastKey': 1, - 'flatMap': 1, - 'forEach': 1, - 'forEachRight': 1, - 'forIn': 1, - 'forInRight': 1, - 'forOwn': 1, - 'forOwnRight': 1, - 'isEqualWith': 2, - 'isMatchWith': 2, - 'map': 1, - 'mapKeys': 1, - 'mapValues': 1, - 'partition': 1, - 'reduce': 2, - 'reduceRight': 2, - 'reject': 1, - 'remove': 1, - 'some': 1, - 'takeRightWhile': 1, - 'takeWhile': 1, - 'times': 1, - 'transform': 2 - }, - - /** Used to map ary to method names. */ - 'aryMethodMap': { - 1: ( - 'attempt,ceil,create,curry,curryRight,floor,fromPairs,iteratee,invert,over,' + - 'overEvery,overSome,memoize,method,methodOf,mixin,rest,reverse,round,' + - 'runInContext,template,trim,trimLeft,trimRight,uniqueId,words').split(','), - 2: ( - 'add,ary,assign,at,bind,bindKey,cloneDeepWith,cloneWith,concat,countBy,curryN,' + - 'curryRightN,debounce,defaults,defaultsDeep,delay,difference,drop,dropRight,' + - 'dropRightWhile,dropWhile,endsWith,eq,every,extend,filter,find,find,findIndex,' + - 'findKey,findLast,findLastIndex,findLastKey,flatMap,forEach,forEachRight,' + - 'forIn,forInRight,forOwn,forOwnRight,get,groupBy,includes,indexBy,indexOf,' + - 'intersection,invoke,invokeMap,isMatch,lastIndexOf,map,mapKeys,mapValues,' + - 'matchesProperty,maxBy,mean,minBy,merge,omit,orderBy,overArgs,pad,padLeft,' + - 'padRight,parseInt,partition,pick,pull,pullAll,pullAt,random,range,rangeRight,' + - 'rearg,reject,remove,repeat,result,sampleSize,some,sortBy,sortedIndexBy,' + - 'sortedLastIndexBy,sortedUniqBy,startsWith,subtract,sumBy,take,takeRight,' + - 'takeRightWhile,takeWhile,throttle,times,truncate,union,uniqBy,without,wrap,' + - 'xor,zip,zipObject').split(','), - 3: ( - 'assignWith,clamp,differenceBy,extendWith,getOr,inRange,intersectionBy,' + - 'isEqualWith,isMatchWith,mergeWith,omitBy,pickBy,pullAllBy,reduce,' + - 'reduceRight,set,slice,transform,unionBy,xorBy,zipWith').split(','), - 4: - ['fill', 'setWith'] - }, - - /** Used to map ary to rearg configs by method ary. */ - 'aryReargMap': { - 2: [1, 0], - 3: [2, 1, 0], - 4: [3, 2, 0, 1] - }, - - /** Used to map ary to rearg configs by method names. */ - 'methodReargMap': { - 'clamp': [2, 0, 1], - 'reduce': [2, 0, 1], - 'reduceRight': [2, 0, 1], - 'setWith': [3, 2, 1, 0], - 'slice': [2, 0, 1], - 'transform': [2, 0, 1] - }, - - /** Used to iterate `mapping.aryMethodMap` keys. */ - 'caps': [1, 2, 3, 4], - - /** Used to map keys to other keys. */ - 'keyMap': { - 'curryN': 'curry', - 'curryRightN': 'curryRight', - 'getOr': 'get' - }, - - /** Used to identify methods which mutate arrays or objects. */ - 'mutateMap': { - 'array': { - 'fill': true, - 'pull': true, - 'pullAll': true, - 'pullAllBy': true, - 'pullAt': true, - 'remove': true, - 'reverse': true - }, - 'object': { - 'assign': true, - 'assignWith': true, - 'defaults': true, - 'defaultsDeep': true, - 'extend': true, - 'extendWith': true, - 'merge': true, - 'mergeWith': true - }, - 'set': { - 'set': true, - 'setWith': true - } - }, - - /** Used to track methods that skip `_.rearg`. */ - 'skipReargMap': { - 'difference': true, - 'matchesProperty': true, - 'random': true, - 'range': true, - 'rangeRight': true, - 'zip': true, - 'zipObject': true - } -}; diff --git a/fromPairs.js b/fromPairs.js index aa5c2803d..c18c1e386 100644 --- a/fromPairs.js +++ b/fromPairs.js @@ -1,5 +1,3 @@ -var baseSet = require('./internal/baseSet'); - /** * The inverse of `_.toPairs`; this method returns an object composed * from key-value `pairs`. @@ -21,7 +19,7 @@ function fromPairs(pairs) { while (++index < length) { var pair = pairs[index]; - baseSet(result, pair[0], pair[1]); + result[pair[0]] = pair[1]; } return result; } diff --git a/groupBy.js b/groupBy.js index 7950a0666..b8325ec93 100644 --- a/groupBy.js +++ b/groupBy.js @@ -9,14 +9,14 @@ 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. + * of each key is an array of 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. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * diff --git a/internal/Symbol.js b/internal/Symbol.js new file mode 100644 index 000000000..9f903d2a8 --- /dev/null +++ b/internal/Symbol.js @@ -0,0 +1,4 @@ +/** Built-in value references. */ +var Symbol = global.Symbol; + +module.exports = Symbol; diff --git a/internal/_Symbol.js b/internal/_Symbol.js deleted file mode 100644 index dc481f51e..000000000 --- a/internal/_Symbol.js +++ /dev/null @@ -1,4 +0,0 @@ -/** Built-in value references. */ -var _Symbol = global.Symbol; - -module.exports = _Symbol; diff --git a/internal/arrayReduce.js b/internal/arrayReduce.js index db95dc49a..6a355bce8 100644 --- a/internal/arrayReduce.js +++ b/internal/arrayReduce.js @@ -6,14 +6,14 @@ * @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} [initAccum] Specify using the first element of `array` as the initial value. * @returns {*} Returns the accumulated value. */ -function arrayReduce(array, iteratee, accumulator, initFromArray) { +function arrayReduce(array, iteratee, accumulator, initAccum) { var index = -1, length = array.length; - if (initFromArray && length) { + if (initAccum && length) { accumulator = array[++index]; } while (++index < length) { diff --git a/internal/arrayReduceRight.js b/internal/arrayReduceRight.js index 5301e4a73..b33a2d086 100644 --- a/internal/arrayReduceRight.js +++ b/internal/arrayReduceRight.js @@ -6,12 +6,12 @@ * @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} [initAccum] Specify using the last element of `array` as the initial value. * @returns {*} Returns the accumulated value. */ -function arrayReduceRight(array, iteratee, accumulator, initFromArray) { +function arrayReduceRight(array, iteratee, accumulator, initAccum) { var length = array.length; - if (initFromArray && length) { + if (initAccum && length) { accumulator = array[--length]; } while (length--) { diff --git a/internal/baseFind.js b/internal/baseFind.js index f728c0f6f..535f7f353 100644 --- a/internal/baseFind.js +++ b/internal/baseFind.js @@ -1,7 +1,7 @@ /** * The base implementation of methods like `_.find` and `_.findKey`, without * support for iteratee shorthands, which iterates over `collection` using - * the provided `eachFunc`. + * `eachFunc`. * * @private * @param {Array|Object} collection The collection to search. diff --git a/internal/baseInvoke.js b/internal/baseInvoke.js index 2df5c09ad..e47ebbfa2 100644 --- a/internal/baseInvoke.js +++ b/internal/baseInvoke.js @@ -8,7 +8,6 @@ var apply = require('./apply'), * 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. diff --git a/internal/baseIsMatch.js b/internal/baseIsMatch.js index f763df602..1f7a6045d 100644 --- a/internal/baseIsMatch.js +++ b/internal/baseIsMatch.js @@ -47,7 +47,10 @@ function baseIsMatch(object, source, matchData, customizer) { 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)) { + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) + : result + )) { return false; } } diff --git a/internal/baseMerge.js b/internal/baseMerge.js index c0fcc060e..48d28314d 100644 --- a/internal/baseMerge.js +++ b/internal/baseMerge.js @@ -13,10 +13,11 @@ var Stack = require('./Stack'), * @private * @param {Object} object The destination object. * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. * @param {Function} [customizer] The function to customize merged values. * @param {Object} [stack] Tracks traversed source values and their merged counterparts. */ -function baseMerge(object, source, customizer, stack) { +function baseMerge(object, source, srcIndex, customizer, stack) { if (object === source) { return; } @@ -28,7 +29,7 @@ function baseMerge(object, source, customizer, stack) { } if (isObject(srcValue)) { stack || (stack = new Stack); - baseMergeDeep(object, source, key, baseMerge, customizer, stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { var newValue = customizer ? customizer(object[key], srcValue, (key + ''), object, source, stack) : undefined; diff --git a/internal/baseMergeDeep.js b/internal/baseMergeDeep.js index b6c131f8f..c7f3c40c4 100644 --- a/internal/baseMergeDeep.js +++ b/internal/baseMergeDeep.js @@ -19,11 +19,12 @@ var assignMergeValue = require('./assignMergeValue'), * @param {Object} object The destination object. * @param {Object} source The source object. * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. * @param {Function} mergeFunc The function to merge values. * @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, stack) { +function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { var objValue = object[key], srcValue = source[key], stacked = stack.get(srcValue) || stack.get(objValue); @@ -38,24 +39,36 @@ function baseMergeDeep(object, source, key, mergeFunc, customizer, stack) { if (isCommon) { newValue = srcValue; if (isArray(srcValue) || isTypedArray(srcValue)) { - newValue = isArray(objValue) - ? objValue - : ((isArrayLikeObject(objValue)) ? copyArray(objValue) : baseClone(srcValue)); + if (isArray(objValue)) { + newValue = srcIndex ? copyArray(objValue) : objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else { + newValue = baseClone(srcValue); + } } else if (isPlainObject(srcValue) || isArguments(srcValue)) { - newValue = isArguments(objValue) - ? toPlainObject(objValue) - : (isObject(objValue) ? objValue : baseClone(srcValue)); + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = baseClone(srcValue); + } + else { + newValue = srcIndex ? baseClone(objValue) : objValue; + } } else { - isCommon = isFunction(srcValue); + isCommon = false; } } stack.set(srcValue, newValue); if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). - mergeFunc(newValue, srcValue, customizer, stack); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); } assignMergeValue(object, key, newValue); } diff --git a/internal/basePickBy.js b/internal/basePickBy.js index 48e17757d..2d7dd2041 100644 --- a/internal/basePickBy.js +++ b/internal/basePickBy.js @@ -11,7 +11,7 @@ var baseForIn = require('./baseForIn'); function basePickBy(object, predicate) { var result = {}; baseForIn(object, function(value, key) { - if (predicate(value)) { + if (predicate(value, key)) { result[key] = value; } }); diff --git a/internal/baseReduce.js b/internal/baseReduce.js index 9ab844221..6ec544251 100644 --- a/internal/baseReduce.js +++ b/internal/baseReduce.js @@ -1,20 +1,19 @@ /** * The base implementation of `_.reduce` and `_.reduceRight`, without support - * for iteratee shorthands, which iterates over `collection` using the provided - * `eachFunc`. + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. * * @private * @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} initAccum 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. */ -function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { +function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { eachFunc(collection, function(value, index, collection) { - accumulator = initFromCollection - ? (initFromCollection = false, value) + accumulator = initAccum + ? (initAccum = false, value) : iteratee(accumulator, value, index, collection); }); return accumulator; diff --git a/internal/cloneSymbol.js b/internal/cloneSymbol.js index d5480ebcd..1310b3a51 100644 --- a/internal/cloneSymbol.js +++ b/internal/cloneSymbol.js @@ -1,8 +1,8 @@ -var _Symbol = require('./_Symbol'); +var Symbol = require('./Symbol'); /** Used to convert symbols to primitives and strings. */ -var symbolProto = _Symbol ? _Symbol.prototype : undefined, - symbolValueOf = _Symbol ? symbolProto.valueOf : undefined; +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = Symbol ? symbolProto.valueOf : undefined; /** * Creates a clone of the `symbol` object. @@ -12,7 +12,7 @@ var symbolProto = _Symbol ? _Symbol.prototype : undefined, * @returns {Object} Returns the cloned symbol object. */ function cloneSymbol(symbol) { - return _Symbol ? Object(symbolValueOf.call(symbol)) : {}; + return Symbol ? Object(symbolValueOf.call(symbol)) : {}; } module.exports = cloneSymbol; diff --git a/internal/createAssigner.js b/internal/createAssigner.js index c8dfd19f9..7dbbc0c64 100644 --- a/internal/createAssigner.js +++ b/internal/createAssigner.js @@ -24,7 +24,7 @@ function createAssigner(assigner) { while (++index < length) { var source = sources[index]; if (source) { - assigner(object, source, customizer); + assigner(object, source, index, customizer); } } return object; diff --git a/internal/createCaseFirst.js b/internal/createCaseFirst.js index 10b6c6ad0..2c29e0137 100644 --- a/internal/createCaseFirst.js +++ b/internal/createCaseFirst.js @@ -3,14 +3,15 @@ var stringToArray = require('./stringToArray'), /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', 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 + ']'); +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /** * Creates a function like `_.lowerFirst`. diff --git a/internal/createPadding.js b/internal/createPadding.js index a1983f949..0e5a02526 100644 --- a/internal/createPadding.js +++ b/internal/createPadding.js @@ -5,14 +5,15 @@ var repeat = require('../repeat'), /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', 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 + ']'); +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil; diff --git a/internal/equalByTag.js b/internal/equalByTag.js index 9a77d47c1..ba00fa3b3 100644 --- a/internal/equalByTag.js +++ b/internal/equalByTag.js @@ -1,5 +1,5 @@ -var Uint8Array = require('./Uint8Array'), - _Symbol = require('./_Symbol'), +var Symbol = require('./Symbol'), + Uint8Array = require('./Uint8Array'), mapToArray = require('./mapToArray'), setToArray = require('./setToArray'); @@ -21,8 +21,8 @@ var boolTag = '[object Boolean]', var arrayBufferTag = '[object ArrayBuffer]'; /** Used to convert symbols to primitives and strings. */ -var symbolProto = _Symbol ? _Symbol.prototype : undefined, - symbolValueOf = _Symbol ? symbolProto.valueOf : undefined; +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = Symbol ? symbolProto.valueOf : undefined; /** * A specialized version of `baseIsEqualDeep` for comparing objects of @@ -80,7 +80,7 @@ function equalByTag(object, other, tag, equalFunc, customizer, bitmask) { equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG); case symbolTag: - return !!_Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); + return !!Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); } return false; } diff --git a/internal/equalObjects.js b/internal/equalObjects.js index 86966b1be..ad95a755e 100644 --- a/internal/equalObjects.js +++ b/internal/equalObjects.js @@ -2,8 +2,7 @@ var baseHas = require('./baseHas'), keys = require('../keys'); /** Used to compose bitmasks for comparison styles. */ -var UNORDERED_COMPARE_FLAG = 1, - PARTIAL_COMPARE_FLAG = 2; +var PARTIAL_COMPARE_FLAG = 2; /** * A specialized version of `baseIsEqualDeep` for objects with support for @@ -20,7 +19,6 @@ var UNORDERED_COMPARE_FLAG = 1, */ 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), @@ -32,8 +30,7 @@ function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { var index = objLength; while (index--) { var key = objProps[index]; - if (!(isPartial ? key in other : baseHas(other, key)) || - !(isUnordered || key == othProps[index])) { + if (!(isPartial ? key in other : baseHas(other, key))) { return false; } } diff --git a/internal/getFuncName.js b/internal/getFuncName.js index ed92867d6..4a555ad13 100644 --- a/internal/getFuncName.js +++ b/internal/getFuncName.js @@ -1,5 +1,11 @@ var realNames = require('./realNames'); +/** Used for built-in method references. */ +var objectProto = global.Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + /** * Gets the name of `func`. * @@ -10,7 +16,7 @@ var realNames = require('./realNames'); function getFuncName(func) { var result = (func.name + ''), array = realNames[result], - length = array ? array.length : 0; + length = hasOwnProperty.call(realNames, result) ? array.length : 0; while (length--) { var data = array[length], diff --git a/internal/mergeDefaults.js b/internal/mergeDefaults.js index d17bd1bac..97ab718ec 100644 --- a/internal/mergeDefaults.js +++ b/internal/mergeDefaults.js @@ -1,5 +1,4 @@ -var baseClone = require('./baseClone'), - baseMerge = require('./baseMerge'), +var baseMerge = require('./baseMerge'), isObject = require('../isObject'); /** @@ -17,9 +16,9 @@ var baseClone = require('./baseClone'), function mergeDefaults(objValue, srcValue, key, object, source, stack) { if (isObject(objValue) && isObject(srcValue)) { stack.set(srcValue, objValue); - baseMerge(objValue, srcValue, mergeDefaults, stack); + baseMerge(objValue, srcValue, undefined, mergeDefaults, stack); } - return objValue === undefined ? baseClone(srcValue) : objValue; + return objValue; } module.exports = mergeDefaults; diff --git a/internal/stringSize.js b/internal/stringSize.js index a97dbcb7f..7aa9f4125 100644 --- a/internal/stringSize.js +++ b/internal/stringSize.js @@ -1,12 +1,14 @@ /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', rsVarRange = '\\ufe0e\\ufe0f'; /** Used to compose unicode capture groups. */ var rsAstral = '[' + rsAstralRange + ']', - rsCombo = '[' + rsComboRange + ']', - rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', rsNonAstral = '[^' + rsAstralRange + ']', rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', @@ -20,14 +22,15 @@ var reOptMod = rsModifier + '?', 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'); +var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + 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 + ']'); +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /** * Gets the number of symbols in `string`. * + * @private * @param {string} string The string to inspect. * @returns {number} Returns the string size. */ diff --git a/internal/stringToArray.js b/internal/stringToArray.js index 9176f35e0..90986f09b 100644 --- a/internal/stringToArray.js +++ b/internal/stringToArray.js @@ -1,12 +1,14 @@ /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', rsVarRange = '\\ufe0e\\ufe0f'; /** Used to compose unicode capture groups. */ var rsAstral = '[' + rsAstralRange + ']', - rsCombo = '[' + rsComboRange + ']', - rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', rsNonAstral = '[^' + rsAstralRange + ']', rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', @@ -20,7 +22,7 @@ var reOptMod = rsModifier + '?', 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'); +var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); /** * Converts `string` to an array. diff --git a/intersection.js b/intersection.js index 55bf7a0e0..6a33fcf41 100644 --- a/intersection.js +++ b/intersection.js @@ -14,6 +14,7 @@ var arrayMap = require('./internal/arrayMap'), * @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] */ diff --git a/isEqualWith.js b/isEqualWith.js index 3f21b88e0..3262db9f6 100644 --- a/isEqualWith.js +++ b/isEqualWith.js @@ -3,7 +3,7 @@ var baseIsEqual = require('./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: + * handled by the method instead. The `customizer` is invoked with up to six arguments: * (objValue, othValue [, index|key, object, other, stack]). * * @static diff --git a/isMatchWith.js b/isMatchWith.js index d3deea50a..7b1345ae7 100644 --- a/isMatchWith.js +++ b/isMatchWith.js @@ -4,7 +4,7 @@ var baseIsMatch = require('./internal/baseIsMatch'), /** * 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 + * are handled by the method instead. The `customizer` is invoked with five * arguments: (objValue, srcValue, index|key, object, source). * * @static diff --git a/keyBy.js b/keyBy.js index e71bc97db..8a4bac5b3 100644 --- a/keyBy.js +++ b/keyBy.js @@ -10,7 +10,7 @@ var createAggregator = require('./internal/createAggregator'); * @memberOf _ * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * @@ -19,13 +19,13 @@ var createAggregator = require('./internal/createAggregator'); * { '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 } } + * + * _.keyBy(keyData, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { result[key] = value; diff --git a/lodash.js b/lodash.js index e20df3884..95aef7960 100644 --- a/lodash.js +++ b/lodash.js @@ -1,6 +1,6 @@ /** * @license - * lodash 4.0.0 (Custom Build) + * lodash 4.0.1 (Custom Build) * Build: `lodash -d -o ./lodash.js` * Copyright 2012-2016 The Dojo Foundation * Based on Underscore.js 1.8.3 @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.0.0'; + var VERSION = '4.0.1'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, @@ -163,7 +163,8 @@ /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', rsDingbatRange = '\\u2700-\\u27bf', rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', @@ -177,12 +178,13 @@ /** Used to compose unicode capture groups. */ var rsAstral = '[' + rsAstralRange + ']', rsBreak = '[' + rsBreakRange + ']', - rsCombo = '[' + rsComboRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', rsDigits = '\\d+', rsDingbat = '[' + rsDingbatRange + ']', rsLower = '[' + rsLowerRange + ']', rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', - rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', rsNonAstral = '[^' + rsAstralRange + ']', rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', @@ -199,14 +201,17 @@ rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; - /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ var reComboMark = RegExp(rsCombo, 'g'); /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ - var reComplexSymbol = RegExp(rsSymbol + rsSeq, 'g'); + var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + 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 + ']'); + var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /** Used to match non-compound words composed of alphanumeric characters. */ var reBasicWord = /[a-zA-Z0-9]+/g; @@ -216,7 +221,8 @@ rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', rsUpper + '?' + rsLowerMisc + '+', - rsDigits + '(?:' + rsLowerMisc + '+)?', + rsUpper + '+', + rsDigits, rsEmoji ].join('|'), 'g'); @@ -597,14 +603,14 @@ * @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} [initAccum] Specify using the first element of `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduce(array, iteratee, accumulator, initFromArray) { + function arrayReduce(array, iteratee, accumulator, initAccum) { var index = -1, length = array.length; - if (initFromArray && length) { + if (initAccum && length) { accumulator = array[++index]; } while (++index < length) { @@ -621,12 +627,12 @@ * @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} [initAccum] Specify using the last element of `array` as the initial value. * @returns {*} Returns the accumulated value. */ - function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + function arrayReduceRight(array, iteratee, accumulator, initAccum) { var length = array.length; - if (initFromArray && length) { + if (initAccum && length) { accumulator = array[--length]; } while (length--) { @@ -688,7 +694,7 @@ /** * The base implementation of methods like `_.find` and `_.findKey`, without * support for iteratee shorthands, which iterates over `collection` using - * the provided `eachFunc`. + * `eachFunc`. * * @private * @param {Array|Object} collection The collection to search. @@ -756,21 +762,20 @@ /** * The base implementation of `_.reduce` and `_.reduceRight`, without support - * for iteratee shorthands, which iterates over `collection` using the provided - * `eachFunc`. + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. * * @private * @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} initAccum 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. */ - function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { eachFunc(collection, function(value, index, collection) { - accumulator = initFromCollection - ? (initFromCollection = false, value) + accumulator = initAccum + ? (initAccum = false, value) : iteratee(accumulator, value, index, collection); }); return accumulator; @@ -1164,6 +1169,7 @@ /** * Gets the number of symbols in `string`. * + * @private * @param {string} string The string to inspect. * @returns {number} Returns the string size. */ @@ -1279,14 +1285,14 @@ ); /** Built-in value references. */ - var _Symbol = context.Symbol, - Reflect = context.Reflect, + var Reflect = context.Reflect, + Symbol = context.Symbol, Uint8Array = context.Uint8Array, clearTimeout = context.clearTimeout, enumerate = Reflect ? Reflect.enumerate : undefined, getPrototypeOf = Object.getPrototypeOf, getOwnPropertySymbols = Object.getOwnPropertySymbols, - iteratorSymbol = typeof (iteratorSymbol = _Symbol && _Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined, + iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined, propertyIsEnumerable = objectProto.propertyIsEnumerable, setTimeout = context.setTimeout, splice = arrayProto.splice; @@ -1317,9 +1323,9 @@ setCtorString = Set ? funcToString.call(Set) : ''; /** Used to convert symbols to primitives and strings. */ - var symbolProto = _Symbol ? _Symbol.prototype : undefined, - symbolValueOf = _Symbol ? symbolProto.valueOf : undefined, - symbolToString = _Symbol ? symbolProto.toString : undefined; + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = Symbol ? symbolProto.valueOf : undefined, + symbolToString = Symbol ? symbolProto.toString : undefined; /** Used to lookup unminified function names. */ var realNames = {}; @@ -1367,13 +1373,12 @@ * 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`, + * `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, `curry`, * `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`, - * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`, + * `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`, + * `flowRight`, `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`, @@ -1392,22 +1397,23 @@ * `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`, + * `findLast`, `findLastIndex`, `findLastKey`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `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 _ @@ -2667,7 +2673,6 @@ * 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. @@ -2810,7 +2815,10 @@ 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)) { + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) + : result + )) { return false; } } @@ -2946,10 +2954,11 @@ * @private * @param {Object} object The destination object. * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. * @param {Function} [customizer] The function to customize merged values. * @param {Object} [stack] Tracks traversed source values and their merged counterparts. */ - function baseMerge(object, source, customizer, stack) { + function baseMerge(object, source, srcIndex, customizer, stack) { if (object === source) { return; } @@ -2961,7 +2970,7 @@ } if (isObject(srcValue)) { stack || (stack = new Stack); - baseMergeDeep(object, source, key, baseMerge, customizer, stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { var newValue = customizer ? customizer(object[key], srcValue, (key + ''), object, source, stack) : undefined; @@ -2982,11 +2991,12 @@ * @param {Object} object The destination object. * @param {Object} source The source object. * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. * @param {Function} mergeFunc The function to merge values. * @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, stack) { + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { var objValue = object[key], srcValue = source[key], stacked = stack.get(srcValue) || stack.get(objValue); @@ -3001,24 +3011,36 @@ if (isCommon) { newValue = srcValue; if (isArray(srcValue) || isTypedArray(srcValue)) { - newValue = isArray(objValue) - ? objValue - : ((isArrayLikeObject(objValue)) ? copyArray(objValue) : baseClone(srcValue)); + if (isArray(objValue)) { + newValue = srcIndex ? copyArray(objValue) : objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else { + newValue = baseClone(srcValue); + } } else if (isPlainObject(srcValue) || isArguments(srcValue)) { - newValue = isArguments(objValue) - ? toPlainObject(objValue) - : (isObject(objValue) ? objValue : baseClone(srcValue)); + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = baseClone(srcValue); + } + else { + newValue = srcIndex ? baseClone(objValue) : objValue; + } } else { - isCommon = isFunction(srcValue); + isCommon = false; } } stack.set(srcValue, newValue); if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). - mergeFunc(newValue, srcValue, customizer, stack); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); } assignMergeValue(object, key, newValue); } @@ -3082,7 +3104,7 @@ function basePickBy(object, predicate) { var result = {}; baseForIn(object, function(value, key) { - if (predicate(value)) { + if (predicate(value, key)) { result[key] = value; } }); @@ -3667,7 +3689,7 @@ * @returns {Object} Returns the cloned symbol object. */ function cloneSymbol(symbol) { - return _Symbol ? Object(symbolValueOf.call(symbol)) : {}; + return Symbol ? Object(symbolValueOf.call(symbol)) : {}; } /** @@ -3870,7 +3892,7 @@ while (++index < length) { var source = sources[index]; if (source) { - assigner(object, source, customizer); + assigner(object, source, index, customizer); } } return object; @@ -4555,7 +4577,7 @@ equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG); case symbolTag: - return !!_Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); + return !!Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); } return false; } @@ -4575,7 +4597,6 @@ */ 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), @@ -4587,8 +4608,7 @@ var index = objLength; while (index--) { var key = objProps[index]; - if (!(isPartial ? key in other : baseHas(other, key)) || - !(isUnordered || key == othProps[index])) { + if (!(isPartial ? key in other : baseHas(other, key))) { return false; } } @@ -4658,7 +4678,7 @@ function getFuncName(func) { var result = (func.name + ''), array = realNames[result], - length = array ? array.length : 0; + length = hasOwnProperty.call(realNames, result) ? array.length : 0; while (length--) { var data = array[length], @@ -5099,9 +5119,9 @@ function mergeDefaults(objValue, srcValue, key, object, source, stack) { if (isObject(objValue) && isObject(srcValue)) { stack.set(srcValue, objValue); - baseMerge(objValue, srcValue, mergeDefaults, stack); + baseMerge(objValue, srcValue, undefined, mergeDefaults, stack); } - return objValue === undefined ? baseClone(srcValue) : objValue; + return objValue; } /** @@ -5315,8 +5335,11 @@ * // => [1] */ var concat = rest(function(array, values) { + if (!isArray(array)) { + array = array == null ? [] : [Object(array)]; + } values = baseFlatten(values); - return arrayConcat(isArray(array) ? array : [Object(array)], values); + return arrayConcat(array, values); }); /** @@ -5748,7 +5771,7 @@ while (++index < length) { var pair = pairs[index]; - baseSet(result, pair[0], pair[1]); + result[pair[0]] = pair[1]; } return result; } @@ -5837,6 +5860,7 @@ * @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] */ @@ -6029,7 +6053,7 @@ * * var array = [1, 2, 3, 1, 2, 3]; * - * _.pull(array, [2, 3]); + * _.pullAll(array, [2, 3]); * console.log(array); * // => [1, 1] */ @@ -6153,6 +6177,7 @@ * **Note:** This method mutates `array` and is based on * [`Array#reverse`](https://mdn.io/Array/reverse). * + * @static * @memberOf _ * @category Array * @returns {Array} Returns `array`. @@ -7111,7 +7136,7 @@ /** * This method is the wrapper version of `_.flatMap`. * - * @static + * @name flatMap * @memberOf _ * @category Seq * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. @@ -7262,7 +7287,7 @@ * * @name value * @memberOf _ - * @alias run, toJSON, valueOf + * @alias toJSON, valueOf * @category Seq * @returns {*} Returns the resolved unwrapped value. * @example @@ -7286,7 +7311,7 @@ * @memberOf _ * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * @@ -7510,14 +7535,14 @@ /** * 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. + * of each key is an array of 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. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * @@ -7622,7 +7647,7 @@ * @memberOf _ * @category Collection * @param {Array|Object} collection The collection to iterate over. - * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element. + * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * @@ -7631,13 +7656,13 @@ * { '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 } } + * + * _.keyBy(keyData, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { result[key] = value; @@ -7669,11 +7694,11 @@ * return n * n; * } * - * _.map([1, 2], square); - * // => [3, 6] + * _.map([4, 8], square); + * // => [16, 64] * - * _.map({ 'a': 1, 'b': 2 }, square); - * // => [3, 6] (iteration order is not guaranteed) + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) * * var users = [ * { 'user': 'barney' }, @@ -7732,9 +7757,9 @@ /** * 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). + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). * * @static * @memberOf _ @@ -7806,9 +7831,9 @@ */ function reduce(collection, iteratee, accumulator) { var func = isArray(collection) ? arrayReduce : baseReduce, - initFromCollection = arguments.length < 3; + initAccum = arguments.length < 3; - return func(collection, getIteratee(iteratee, 4), accumulator, initFromCollection, baseEach); + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); } /** @@ -7833,9 +7858,9 @@ */ function reduceRight(collection, iteratee, accumulator) { var func = isArray(collection) ? arrayReduceRight : baseReduce, - initFromCollection = arguments.length < 3; + initAccum = arguments.length < 3; - return func(collection, getIteratee(iteratee, 4), accumulator, initFromCollection, baseEachRight); + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); } /** @@ -7899,7 +7924,8 @@ } /** - * Gets `n` random elements from `collection`. + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. * * @static * @memberOf _ @@ -7909,8 +7935,11 @@ * @returns {Array} Returns the random elements. * @example * - * _.sampleSize([1, 2, 3, 4], 2); + * _.sampleSize([1, 2, 3], 2); * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] */ function sampleSize(collection, n) { var index = -1, @@ -9074,7 +9103,7 @@ * 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]). + * up to four arguments; (value [, index|key, object, stack]). * * @static * @memberOf _ @@ -9090,7 +9119,7 @@ * } * } * - * var el = _.clone(document.body, customizer); + * var el = _.cloneWith(document.body, customizer); * * console.log(el === document.body); * // => false @@ -9140,7 +9169,7 @@ * } * } * - * var el = _.cloneDeep(document.body, customizer); + * var el = _.cloneDeepWith(document.body, customizer); * * console.log(el === document.body); * // => false @@ -9468,7 +9497,7 @@ /** * 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: + * handled by the method instead. The `customizer` is invoked with up to six arguments: * (objValue, othValue [, index|key, object, other, stack]). * * @static @@ -9718,7 +9747,7 @@ /** * 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 + * are handled by the method instead. The `customizer` is invoked with five * arguments: (objValue, srcValue, index|key, object, source). * * @static @@ -10189,7 +10218,7 @@ * @memberOf _ * @category Lang * @param {*} value The value to convert. - * @return {number} Returns the converted integer. + * @returns {number} Returns the converted integer. * @example * * _.toLength(3); @@ -10328,7 +10357,7 @@ return ''; } if (isSymbol(value)) { - return _Symbol ? symbolToString.call(value) : ''; + return Symbol ? symbolToString.call(value) : ''; } var result = (value + ''); return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; @@ -10430,7 +10459,7 @@ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); * // => { 'a': 1, 'b': 2 } */ - var assignInWith = createAssigner(function(object, source, customizer) { + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { copyObjectWith(source, keysIn(source), object, customizer); }); @@ -10460,7 +10489,7 @@ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); * // => { 'a': 1, 'b': 2 } */ - var assignWith = createAssigner(function(object, source, customizer) { + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { copyObjectWith(source, keys(source), object, customizer); }); @@ -11140,8 +11169,8 @@ * _.merge(users, ages); * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } */ - var merge = createAssigner(function(object, source) { - baseMerge(object, source); + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); }); /** @@ -11179,8 +11208,8 @@ * _.mergeWith(object, other, customizer); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ - var mergeWith = createAssigner(function(object, source, customizer) { - baseMerge(object, source, customizer); + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); }); /** @@ -11228,9 +11257,9 @@ * // => { 'b': '2' } */ function omitBy(object, predicate) { - predicate = getIteratee(predicate); - return basePickBy(object, function(value) { - return !predicate(value); + predicate = getIteratee(predicate, 2); + return basePickBy(object, function(value, key) { + return !predicate(value, key); }); } @@ -11273,7 +11302,7 @@ * // => { 'a': 1, 'c': 3 } */ function pickBy(object, predicate) { - return object == null ? {} : basePickBy(object, getIteratee(predicate)); + return object == null ? {} : basePickBy(object, getIteratee(predicate, 2)); } /** @@ -12040,7 +12069,7 @@ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E) + * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#x15.1.2.2) * of `parseInt`. * * @static @@ -12832,7 +12861,7 @@ * [_.matches({ 'a': 1 }), _.constant('matches A')], * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], * [_.constant(true), _.constant('no match')] - * ]) + * ]); * * func({ 'a': 1, 'b': 2 }); * // => 'matches A' @@ -13203,7 +13232,9 @@ * var lodash = _.noConflict(); */ function noConflict() { - root._ = oldDash; + if (root._ === this) { + root._ = oldDash; + } return this; } @@ -13368,8 +13399,7 @@ * 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. + * it's set to `start` with `start` then set to `0`. * * **Note:** JavaScript follows the IEEE-754 standard for resolving * floating-point values which can produce unexpected results. @@ -13637,7 +13667,7 @@ * * var objects = [{ 'n': 1 }, { 'n': 2 }]; * - * _.maxBy(objects, function(o) { return o.a; }); + * _.maxBy(objects, function(o) { return o.n; }); * // => { 'n': 2 } * * // using the `_.property` iteratee shorthand @@ -13705,7 +13735,7 @@ * * var objects = [{ 'n': 1 }, { 'n': 2 }]; * - * _.minBy(objects, function(o) { return o.a; }); + * _.minBy(objects, function(o) { return o.n; }); * // => { 'n': 1 } * * // using the `_.property` iteratee shorthand @@ -13989,8 +14019,6 @@ lodash.zipWith = zipWith; // Add aliases. - lodash.each = forEach; - lodash.eachRight = forEachRight; lodash.extend = assignIn; lodash.extendWith = assignInWith; @@ -14133,6 +14161,8 @@ lodash.upperFirst = upperFirst; // Add aliases. + lodash.each = forEach; + lodash.eachRight = forEachRight; lodash.first = head; mixin(lodash, (function() { diff --git a/map.js b/map.js index 0f8ce833b..31da57788 100644 --- a/map.js +++ b/map.js @@ -29,11 +29,11 @@ var arrayMap = require('./internal/arrayMap'), * return n * n; * } * - * _.map([1, 2], square); - * // => [3, 6] + * _.map([4, 8], square); + * // => [16, 64] * - * _.map({ 'a': 1, 'b': 2 }, square); - * // => [3, 6] (iteration order is not guaranteed) + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) * * var users = [ * { 'user': 'barney' }, diff --git a/maxBy.js b/maxBy.js index 5a7200bd9..b5170ef30 100644 --- a/maxBy.js +++ b/maxBy.js @@ -17,7 +17,7 @@ var baseExtremum = require('./internal/baseExtremum'), * * var objects = [{ 'n': 1 }, { 'n': 2 }]; * - * _.maxBy(objects, function(o) { return o.a; }); + * _.maxBy(objects, function(o) { return o.n; }); * // => { 'n': 2 } * * // using the `_.property` iteratee shorthand diff --git a/merge.js b/merge.js index dd90d6939..d22d9daeb 100644 --- a/merge.js +++ b/merge.js @@ -30,8 +30,8 @@ var baseMerge = require('./internal/baseMerge'), * _.merge(users, ages); * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } */ -var merge = createAssigner(function(object, source) { - baseMerge(object, source); +var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); }); module.exports = merge; diff --git a/mergeWith.js b/mergeWith.js index dde4198c2..2555741c6 100644 --- a/mergeWith.js +++ b/mergeWith.js @@ -36,8 +36,8 @@ var baseMerge = require('./internal/baseMerge'), * _.mergeWith(object, other, customizer); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ -var mergeWith = createAssigner(function(object, source, customizer) { - baseMerge(object, source, customizer); +var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); }); module.exports = mergeWith; diff --git a/minBy.js b/minBy.js index 187fd763c..cb90acec5 100644 --- a/minBy.js +++ b/minBy.js @@ -17,7 +17,7 @@ var baseExtremum = require('./internal/baseExtremum'), * * var objects = [{ 'n': 1 }, { 'n': 2 }]; * - * _.minBy(objects, function(o) { return o.a; }); + * _.minBy(objects, function(o) { return o.n; }); * // => { 'n': 1 } * * // using the `_.property` iteratee shorthand diff --git a/object.js b/object.js index df85280c9..6bd7cf071 100644 --- a/object.js +++ b/object.js @@ -6,6 +6,8 @@ module.exports = { 'create': require('./create'), 'defaults': require('./defaults'), 'defaultsDeep': require('./defaultsDeep'), + 'extend': require('./extend'), + 'extendWith': require('./extendWith'), 'findKey': require('./findKey'), 'findLastKey': require('./findLastKey'), 'forIn': require('./forIn'), diff --git a/omitBy.js b/omitBy.js index 1a51e6fe4..1230d0149 100644 --- a/omitBy.js +++ b/omitBy.js @@ -20,9 +20,9 @@ var baseIteratee = require('./internal/baseIteratee'), * // => { 'b': '2' } */ function omitBy(object, predicate) { - predicate = baseIteratee(predicate); - return basePickBy(object, function(value) { - return !predicate(value); + predicate = baseIteratee(predicate, 2); + return basePickBy(object, function(value, key) { + return !predicate(value, key); }); } diff --git a/package.json b/package.json index 36b3981bb..24f2c988a 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "lodash", - "version": "4.0.0", + "version": "4.0.1", "description": "Lodash modular utilities.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", "license": "MIT", - "main": "index.js", + "main": "lodash.js", "keywords": "modules, stdlib, util", "author": "John-David Dalton (http://allyoucanleet.com/)", "contributors": [ diff --git a/parseInt.js b/parseInt.js index cf45faa2d..789aa0131 100644 --- a/parseInt.js +++ b/parseInt.js @@ -14,7 +14,7 @@ var nativeParseInt = global.parseInt; * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * - * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E) + * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#x15.1.2.2) * of `parseInt`. * * @static diff --git a/partition.js b/partition.js index c7c8f60f9..f33f13b2c 100644 --- a/partition.js +++ b/partition.js @@ -2,9 +2,9 @@ var createAggregator = require('./internal/createAggregator'); /** * Creates an array of elements split into two groups, the first of which - * contains elements `predicate` returns truthy for, while the second of which - * contains elements `predicate` returns falsey for. The predicate is invoked - * with three arguments: (value, index|key, collection). + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). * * @static * @memberOf _ diff --git a/pickBy.js b/pickBy.js index 1e2651a29..5289d8757 100644 --- a/pickBy.js +++ b/pickBy.js @@ -19,7 +19,7 @@ var baseIteratee = require('./internal/baseIteratee'), * // => { 'a': 1, 'c': 3 } */ function pickBy(object, predicate) { - return object == null ? {} : basePickBy(object, baseIteratee(predicate)); + return object == null ? {} : basePickBy(object, baseIteratee(predicate, 2)); } module.exports = pickBy; diff --git a/pullAll.js b/pullAll.js index 55a6f180a..cf4020170 100644 --- a/pullAll.js +++ b/pullAll.js @@ -15,7 +15,7 @@ var basePullAll = require('./internal/basePullAll'); * * var array = [1, 2, 3, 1, 2, 3]; * - * _.pull(array, [2, 3]); + * _.pullAll(array, [2, 3]); * console.log(array); * // => [1, 1] */ diff --git a/range.js b/range.js index 7b6ed9214..f6528304e 100644 --- a/range.js +++ b/range.js @@ -4,8 +4,7 @@ var createRange = require('./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. + * it's set to `start` with `start` then set to `0`. * * **Note:** JavaScript follows the IEEE-754 standard for resolving * floating-point values which can produce unexpected results. diff --git a/reduce.js b/reduce.js index b8e49235f..0ae8064ff 100644 --- a/reduce.js +++ b/reduce.js @@ -41,9 +41,9 @@ var arrayReduce = require('./internal/arrayReduce'), */ function reduce(collection, iteratee, accumulator) { var func = isArray(collection) ? arrayReduce : baseReduce, - initFromCollection = arguments.length < 3; + initAccum = arguments.length < 3; - return func(collection, baseIteratee(iteratee, 4), accumulator, initFromCollection, baseEach); + return func(collection, baseIteratee(iteratee, 4), accumulator, initAccum, baseEach); } module.exports = reduce; diff --git a/reduceRight.js b/reduceRight.js index 6038a281d..2864c5fda 100644 --- a/reduceRight.js +++ b/reduceRight.js @@ -26,9 +26,9 @@ var arrayReduceRight = require('./internal/arrayReduceRight'), */ function reduceRight(collection, iteratee, accumulator) { var func = isArray(collection) ? arrayReduceRight : baseReduce, - initFromCollection = arguments.length < 3; + initAccum = arguments.length < 3; - return func(collection, baseIteratee(iteratee, 4), accumulator, initFromCollection, baseEachRight); + return func(collection, baseIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); } module.exports = reduceRight; diff --git a/reverse.js b/reverse.js index 004cc82ac..7e8b5e03f 100644 --- a/reverse.js +++ b/reverse.js @@ -11,6 +11,7 @@ var nativeReverse = arrayProto.reverse; * **Note:** This method mutates `array` and is based on * [`Array#reverse`](https://mdn.io/Array/reverse). * + * @static * @memberOf _ * @category Array * @returns {Array} Returns `array`. diff --git a/sampleSize.js b/sampleSize.js index eb75cc4e1..947a28dc1 100644 --- a/sampleSize.js +++ b/sampleSize.js @@ -4,7 +4,8 @@ var baseClamp = require('./internal/baseClamp'), toInteger = require('./toInteger'); /** - * Gets `n` random elements from `collection`. + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. * * @static * @memberOf _ @@ -14,8 +15,11 @@ var baseClamp = require('./internal/baseClamp'), * @returns {Array} Returns the random elements. * @example * - * _.sampleSize([1, 2, 3, 4], 2); + * _.sampleSize([1, 2, 3], 2); * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] */ function sampleSize(collection, n) { var index = -1, diff --git a/toArray.js b/toArray.js index f35372fd5..582a0f629 100644 --- a/toArray.js +++ b/toArray.js @@ -1,4 +1,4 @@ -var _Symbol = require('./internal/_Symbol'), +var Symbol = require('./internal/Symbol'), copyArray = require('./internal/copyArray'), getTag = require('./internal/getTag'), isArrayLike = require('./isArrayLike'), @@ -14,7 +14,7 @@ var mapTag = '[object Map]', setTag = '[object Set]'; /** Built-in value references. */ -var iteratorSymbol = typeof (iteratorSymbol = _Symbol && _Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined; +var iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined; /** * Converts `value` to an array. diff --git a/toLength.js b/toLength.js index 1e130f156..d309e7ca5 100644 --- a/toLength.js +++ b/toLength.js @@ -14,7 +14,7 @@ var MAX_ARRAY_LENGTH = 4294967295; * @memberOf _ * @category Lang * @param {*} value The value to convert. - * @return {number} Returns the converted integer. + * @returns {number} Returns the converted integer. * @example * * _.toLength(3); diff --git a/toString.js b/toString.js index b62551983..a9beaf9d7 100644 --- a/toString.js +++ b/toString.js @@ -1,12 +1,12 @@ -var _Symbol = require('./internal/_Symbol'), +var Symbol = require('./internal/Symbol'), isSymbol = require('./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; +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 @@ -37,7 +37,7 @@ function toString(value) { return ''; } if (isSymbol(value)) { - return _Symbol ? symbolToString.call(value) : ''; + return Symbol ? symbolToString.call(value) : ''; } var result = (value + ''); return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; diff --git a/truncate.js b/truncate.js index d19925532..889101bc5 100644 --- a/truncate.js +++ b/truncate.js @@ -14,14 +14,15 @@ var reFlags = /\w*$/; /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', - rsComboRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', 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 + ']'); +var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /** * Truncates `string` if it's longer than the given maximum string length. diff --git a/words.js b/words.js index 05d9785e2..20ea44987 100644 --- a/words.js +++ b/words.js @@ -2,6 +2,8 @@ var toString = require('./toString'); /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', rsDingbatRange = '\\u2700-\\u27bf', rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', @@ -14,11 +16,13 @@ var rsAstralRange = '\\ud800-\\udfff', /** Used to compose unicode capture groups. */ var rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', rsDigits = '\\d+', rsDingbat = '[' + rsDingbatRange + ']', rsLower = '[' + rsLowerRange + ']', rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', - rsModifier = '(?:\\ud83c[\\udffb-\\udfff])', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', rsNonAstral = '[^' + rsAstralRange + ']', rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', @@ -42,7 +46,8 @@ var reComplexWord = RegExp([ rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', rsUpper + '?' + rsLowerMisc + '+', - rsDigits + '(?:' + rsLowerMisc + '+)?', + rsUpper + '+', + rsDigits, rsEmoji ].join('|'), 'g'); diff --git a/wrapperFlatMap.js b/wrapperFlatMap.js index 2f67e5ae8..4c2f85b08 100644 --- a/wrapperFlatMap.js +++ b/wrapperFlatMap.js @@ -1,7 +1,7 @@ /** * This method is the wrapper version of `_.flatMap`. * - * @static + * @name flatMap * @memberOf _ * @category Seq * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration. diff --git a/wrapperLodash.js b/wrapperLodash.js index 5106ab1d9..77cb92e43 100644 --- a/wrapperLodash.js +++ b/wrapperLodash.js @@ -52,13 +52,12 @@ var hasOwnProperty = objectProto.hasOwnProperty; * 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`, + * `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, `curry`, * `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`, - * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`, + * `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`, + * `flowRight`, `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`, @@ -77,22 +76,23 @@ var hasOwnProperty = objectProto.hasOwnProperty; * `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`, + * `findLast`, `findLastIndex`, `findLastKey`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `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 _ diff --git a/wrapperValue.js b/wrapperValue.js index 363f4476a..2f7e908e1 100644 --- a/wrapperValue.js +++ b/wrapperValue.js @@ -5,7 +5,7 @@ var baseWrapperValue = require('./internal/baseWrapperValue'); * * @name value * @memberOf _ - * @alias run, toJSON, valueOf + * @alias toJSON, valueOf * @category Seq * @returns {*} Returns the resolved unwrapped value. * @example