/**
* @license
- * lodash 4.0.0 (Custom Build) <https://lodash.com/>
- * Build: `lodash -d -o ./lodash.js`
+ * lodash 4.5.1 <https://lodash.com/>
* Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
var undefined;
/** Used as the semantic version number. */
- var VERSION = '4.0.0';
+ var VERSION = '4.5.1';
/** Used to compose bitmasks for wrapper metadata. */
var BIND_FLAG = 1,
setTag = '[object Set]',
stringTag = '[object String]',
symbolTag = '[object Symbol]',
- weakMapTag = '[object WeakMap]';
+ weakMapTag = '[object WeakMap]',
+ weakSetTag = '[object WeakSet]';
var arrayBufferTag = '[object ArrayBuffer]',
float32Tag = '[object Float32Array]',
/** 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',
/** 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]',
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;
rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')',
rsUpper + '?' + rsLowerMisc + '+',
- rsDigits + '(?:' + rsLowerMisc + '+)?',
+ rsUpper + '+',
+ rsDigits,
rsEmoji
].join('|'), 'g');
/** Used to assign default `context` object properties. */
var contextProps = [
- 'Array', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function',
- 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
+ 'Array', 'Buffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
+ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_',
'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
freeParseInt = parseInt;
/** Detect free variable `exports`. */
- var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null;
+ var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType)
+ ? exports
+ : undefined;
/** Detect free variable `module`. */
- var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null;
+ var freeModule = (objectTypes[typeof module] && module && !module.nodeType)
+ ? module
+ : undefined;
+
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = (freeModule && freeModule.exports === freeExports)
+ ? freeExports
+ : undefined;
/** Detect free variable `global` from Node.js. */
var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);
/** 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);
* 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')();
+ var root = freeGlobal ||
+ ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) ||
+ freeSelf || thisGlobal || Function('return this')();
/*--------------------------------------------------------------------------*/
* @private
* @param {Function} func The function to invoke.
* @param {*} thisArg The `this` binding of `func`.
- * @param {...*} [args] The arguments to invoke `func` with.
+ * @param {...*} args The arguments to invoke `func` with.
* @returns {*} Returns the result of `func`.
*/
function apply(func, thisArg, args) {
- var length = args ? args.length : 0;
+ var length = args.length;
switch (length) {
case 0: return func.call(thisArg);
case 1: return func.call(thisArg, args[0]);
}
/**
+ * A specialized version of `baseAggregator` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function arrayAggregator(array, setter, iteratee, accumulator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index];
+ setter(accumulator, value, iteratee(value), array);
+ }
+ return accumulator;
+ }
+
+ /**
* Creates a new array concatenating `array` with `other`.
*
* @private
* @param {Array} array The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the first element of `array` as the initial value.
+ * @param {boolean} [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) {
* @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--) {
/**
* 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.
/**
* 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;
}
/**
+ * Gets the number of `placeholder` occurrences in `array`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} placeholder The placeholder to search for.
+ * @returns {number} Returns the placeholder count.
+ */
+ function countHolders(array, placeholder) {
+ var length = array.length,
+ result = 0;
+
+ while (length--) {
+ if (array[length] === placeholder) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ /**
* Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
*
* @private
result = [];
while (++index < length) {
- if (array[index] === placeholder) {
+ var value = array[index];
+ if (value === placeholder || value === PLACEHOLDER) {
array[index] = PLACEHOLDER;
result[++resIndex] = index;
}
/**
* Gets the number of symbols in `string`.
*
+ * @private
* @param {string} string The string to inspect.
* @returns {number} Returns the string size.
*/
* lodash.isFunction(lodash.bar);
* // => true
*
- * // using `context` to mock `Date#getTime` use in `_.now`
+ * // Use `context` to mock `Date#getTime` use in `_.now`.
* var mock = _.runInContext({
* 'Date': function() {
* return { 'getTime': getTimeMock };
* }
* });
*
- * // or creating a suped-up `defer` in Node.js
+ * // Create a suped-up `defer` in Node.js.
* var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
*/
function runInContext(context) {
);
/** Built-in value references. */
- var _Symbol = context.Symbol,
+ var Buffer = moduleExports ? context.Buffer : undefined,
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,
+ objectCreate = Object.create,
propertyIsEnumerable = objectProto.propertyIsEnumerable,
setTimeout = context.setTimeout,
splice = arrayProto.splice;
/** Used to store function metadata. */
var metaMap = WeakMap && new WeakMap;
- /** Used to detect maps and sets. */
+ /** Used to detect maps, sets, and weakmaps. */
var mapCtorString = Map ? funcToString.call(Map) : '',
- setCtorString = Set ? funcToString.call(Set) : '';
+ setCtorString = Set ? funcToString.call(Set) : '',
+ weakMapCtorString = WeakMap ? funcToString.call(WeakMap) : '';
/** 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 = {};
* `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
*
* The chainable wrapper methods are:
- * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`,
- * `at`, `before`, `bind`, `bindAll`, `bindKey`, `chain`, `chunk`, `commit`,
- * `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, `curry`,
- * `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`,
- * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`,
- * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flip`, `flow`,
- * `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`,
- * `forOwnRight`, `fromPairs`, `functions`, `functionsIn`, `groupBy`, `initial`,
- * `intersection`, `intersectionBy`, `intersectionWith`, invert`, `invokeMap`,
- * `iteratee`, `keyBy`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`,
- * `matches`, `matchesProperty`, `memoize`, `merge`, `mergeWith`, `method`,
- * `methodOf`, `mixin`, `negate`, `nthArg`, `omit`, `omitBy`, `once`, `orderBy`,
- * `over`, `overArgs`, `overEvery`, `overSome`, `partial`, `partialRight`,
- * `partition`, `pick`, `pickBy`, `plant`, `property`, `propertyOf`, `pull`,
- * `pullAll`, `pullAllBy`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`,
- * `reject`, `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`,
- * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`,
- * `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`,
- * `toArray`, `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`,
- * `unary`, `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`,
- * `unset`, `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `without`,
- * `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, `zipObject`, and `zipWith`
+ * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
+ * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `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`, `flattenDepth`,
+ * `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, `functionsIn`,
+ * `groupBy`, `initial`, `intersection`, `intersectionBy`, `intersectionWith`,
+ * `invert`, `invertBy`, `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`, `zipObjectDeep`, and `zipWith`
*
* The wrapper methods that are **not** chainable by default are:
* `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
* `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `endsWith`, `eq`,
- * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`,
- * `findLast`, `findLastIndex`, `findLastKey`, `floor`, `get`, `gt`, `gte`,
- * `has`, `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`,
- * `invoke`, `isArguments`, `isArray`, `isArrayLike`, `isArrayLikeObject`,
- * `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`,
- * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMatch`,
- * `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
+ * `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`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`,
+ * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`,
+ * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`,
+ * `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`
+ * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`,
+ * `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
*
* var wrapped = _([1, 2, 3]);
*
- * // returns an unwrapped value
+ * // Returns an unwrapped value.
* wrapped.reduce(_.add);
* // => 6
*
- * // returns a wrapped value
+ * // Returns a wrapped value.
* var squares = wrapped.map(square);
*
* _.isArray(squares);
*
* @static
* @memberOf _
- * @type Object
+ * @type {Object}
*/
lodash.templateSettings = {
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
- * @type RegExp
+ * @type {RegExp}
*/
'escape': reEscape,
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
- * @type RegExp
+ * @type {RegExp}
*/
'evaluate': reEvaluate,
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
- * @type RegExp
+ * @type {RegExp}
*/
'interpolate': reInterpolate,
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
- * @type string
+ * @type {string}
*/
'variable': '',
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
- * @type Object
+ * @type {Object}
*/
'imports': {
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
- * @type Function
+ * @type {Function}
*/
'_': lodash
}
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
*
* @private
+ * @constructor
* @param {*} value The value to wrap.
*/
function LazyWrapper(value) {
resIndex = 0,
takeCount = nativeMin(length, this.__takeCount__);
- if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) {
+ if (!isArr || arrLength < LARGE_ARRAY_SIZE ||
+ (arrLength == length && takeCount == length)) {
return baseWrapperValue(array, this.__actions__);
}
var result = [];
* Creates an hash object.
*
* @private
+ * @constructor
* @returns {Object} Returns the new hash object.
*/
function Hash() {}
* Creates a map cache object to store key-value pairs.
*
* @private
+ * @constructor
* @param {Array} [values] The values to cache.
*/
function MapCache(values) {
* @memberOf MapCache
*/
function mapClear() {
- this.__data__ = { 'hash': new Hash, 'map': Map ? new Map : [], 'string': new Hash };
+ this.__data__ = {
+ 'hash': new Hash,
+ 'map': Map ? new Map : [],
+ 'string': new Hash
+ };
}
/**
* Creates a set cache object to store unique values.
*
* @private
+ * @constructor
* @param {Array} [values] The values to cache.
*/
function SetCache(values) {
* Creates a stack cache object to store key-value pairs.
*
* @private
+ * @constructor
* @param {Array} [values] The values to cache.
*/
function Stack(values) {
*/
function assignValue(object, key, value) {
var objValue = object[key];
- if ((!eq(objValue, value) ||
- (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) ||
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
(value === undefined && !(key in object))) {
object[key] = value;
}
}
/**
+ * Aggregates elements of `collection` on `accumulator` with keys transformed
+ * by `iteratee` and values set by `setter`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseAggregator(collection, setter, iteratee, accumulator) {
+ baseEach(collection, function(value, key, collection) {
+ setter(accumulator, value, iteratee(value), collection);
+ });
+ return accumulator;
+ }
+
+ /**
* The base implementation of `_.assign` without support for multiple sources
* or `customizer` functions.
*
}
/**
+ * Casts `value` to an empty array if it's not an array like object.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the array-like object.
+ */
+ function baseCastArrayLikeObject(value) {
+ return isArrayLikeObject(value) ? value : [];
+ }
+
+ /**
+ * Casts `value` to `identity` if it's not a function.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the array-like object.
+ */
+ function baseCastFunction(value) {
+ return typeof value == 'function' ? value : identity;
+ }
+
+ /**
+ * Casts `value` to a path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the cast property path array.
+ */
+ function baseCastPath(value) {
+ return isArray(value) ? value : stringToPath(value);
+ }
+
+ /**
* The base implementation of `_.clamp` which doesn't coerce arguments to numbers.
*
* @private
var tag = getTag(value),
isFunc = tag == funcTag || tag == genTag;
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
if (isHostObject(value)) {
return object ? value : {};
return copySymbols(value, baseAssign(result, value));
}
} else {
- return cloneableTags[tag]
- ? initCloneByTag(value, tag, isDeep)
- : (object ? value : {});
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result = initCloneByTag(value, tag, isDeep);
}
}
// Check for circular references and return its corresponding clone.
* @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 || {};
- };
- }());
+ function baseCreate(proto) {
+ return isObject(proto) ? objectCreate(proto) : {};
+ }
/**
* The base implementation of `_.delay` and `_.defer` which accepts an array
* @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`.
+ * @param {Object} args The arguments to provide to `func`.
* @returns {number} Returns the timer id.
*/
function baseDelay(func, wait, args) {
*
* @private
* @param {Array} array The array to flatten.
- * @param {boolean} [isDeep] Specify a deep flatten.
+ * @param {number} depth The maximum recursion depth.
* @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) {
+ function baseFlatten(array, depth, isStrict, result) {
result || (result = []);
var index = -1,
while (++index < length) {
var value = array[index];
- if (isArrayLikeObject(value) &&
+ if (depth > 0 && isArrayLikeObject(value) &&
(isStrict || isArray(value) || isArguments(value))) {
- if (isDeep) {
+ if (depth > 1) {
// Recursively flatten arrays (susceptible to call stack limits).
- baseFlatten(value, isDeep, isStrict, result);
+ baseFlatten(value, depth - 1, isStrict, result);
} else {
arrayPush(result, value);
}
/**
* The base implementation of `_.functions` which creates an array of
- * `object` function property names filtered from those provided.
+ * `object` function property names filtered from `props`.
*
* @private
* @param {Object} object The object to inspect.
* @returns {*} Returns the resolved value.
*/
function baseGet(object, path) {
- path = isKey(path, object) ? [path + ''] : baseToPath(path);
+ path = isKey(path, object) ? [path + ''] : baseCastPath(path);
var index = 0,
length = path.length;
var value = array[index],
computed = iteratee ? iteratee(value) : value;
- if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator))) {
+ if (!(seen
+ ? cacheHas(seen, computed)
+ : includes(result, computed, comparator)
+ )) {
var othIndex = othLength;
while (--othIndex) {
var cache = caches[othIndex];
- if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator))) {
+ if (!(cache
+ ? cacheHas(cache, computed)
+ : includes(arrays[othIndex], computed, comparator))
+ ) {
continue outer;
}
}
}
/**
+ * The base implementation of `_.invert` and `_.invertBy` which inverts
+ * `object` with values transformed by `iteratee` and set by `setter`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform values.
+ * @param {Object} accumulator The initial inverted object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseInverter(object, setter, iteratee, accumulator) {
+ baseForOwn(object, function(value, key, object) {
+ setter(accumulator, iteratee(value), key, object);
+ });
+ return accumulator;
+ }
+
+ /**
* 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.
*/
function baseInvoke(object, path, args) {
if (!isKey(path, object)) {
- path = baseToPath(path);
+ path = baseCastPath(path);
object = parent(object, path);
path = last(path);
}
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;
}
}
* 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.
*/
* @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;
}
- var props = (isArray(source) || isTypedArray(source)) ? undefined : keysIn(source);
+ var props = (isArray(source) || isTypedArray(source))
+ ? undefined
+ : keysIn(source);
+
arrayEach(props || source, function(srcValue, key) {
if (props) {
key = srcValue;
}
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;
+ var newValue = customizer
+ ? customizer(object[key], srcValue, (key + ''), object, source, stack)
+ : undefined;
+
if (newValue === undefined) {
newValue = srcValue;
}
* @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);
+ stacked = stack.get(srcValue);
if (stacked) {
assignMergeValue(object, key, stacked);
return;
}
- var newValue = customizer ? customizer(objValue, srcValue, (key + ''), object, source, stack) : undefined,
- isCommon = newValue === undefined;
+ var newValue = customizer
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ var isCommon = newValue === undefined;
if (isCommon) {
newValue = srcValue;
if (isArray(srcValue) || isTypedArray(srcValue)) {
- newValue = isArray(objValue)
- ? objValue
- : ((isArrayLikeObject(objValue)) ? copyArray(objValue) : baseClone(srcValue));
+ if (isArray(objValue)) {
+ newValue = objValue;
+ }
+ else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ }
+ else {
+ isCommon = false;
+ newValue = baseClone(srcValue, true);
+ }
}
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))) {
+ isCommon = false;
+ newValue = baseClone(srcValue, true);
+ }
+ else {
+ newValue = 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);
}
function basePickBy(object, predicate) {
var result = {};
baseForIn(object, function(value, key) {
- if (predicate(value)) {
+ if (predicate(value, key)) {
result[key] = value;
}
});
splice.call(array, index, 1);
}
else if (!isKey(index, array)) {
- var path = baseToPath(index),
+ var path = baseCastPath(index),
object = parent(array, path);
if (object != null) {
* @returns {Object} Returns `object`.
*/
function baseSet(object, path, value, customizer) {
- path = isKey(path, object) ? [path + ''] : baseToPath(path);
+ path = isKey(path, object) ? [path + ''] : baseCastPath(path);
var index = -1,
length = path.length,
var objValue = nested[key];
newValue = customizer ? customizer(objValue, key, nested) : undefined;
if (newValue === undefined) {
- newValue = objValue == null ? (isIndex(path[index + 1]) ? [] : {}) : objValue;
+ newValue = objValue == null
+ ? (isIndex(path[index + 1]) ? [] : {})
+ : objValue;
}
}
assignValue(nested, key, newValue);
}
/**
- * The base implementation of `_.toPath` which only converts `value` to a
- * path if it's not one.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {Array} Returns the property path array.
- */
- function baseToPath(value) {
- return isArray(value) ? value : stringToPath(value);
- }
-
- /**
* The base implementation of `_.uniqBy` without support for iteratee shorthands.
*
* @private
* @returns {boolean} Returns `true` if the property is deleted, else `false`.
*/
function baseUnset(object, path) {
- path = isKey(path, object) ? [path + ''] : baseToPath(path);
+ path = isKey(path, object) ? [path + ''] : baseCastPath(path);
object = parent(object, path);
var key = last(path);
return (object != null && has(object, key)) ? delete object[key] : true;
}
/**
- * Creates a clone of `buffer`.
+ * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
*
* @private
- * @param {ArrayBuffer} buffer The array buffer to clone.
- * @returns {ArrayBuffer} Returns the cloned array buffer.
+ * @param {Array} props The property names.
+ * @param {Array} values The property values.
+ * @param {Function} assignFunc The function to assign values.
+ * @returns {Object} Returns the new object.
*/
- function cloneBuffer(buffer) {
+ function baseZipObject(props, values, assignFunc) {
+ var index = -1,
+ length = props.length,
+ valsLength = values.length,
+ result = {};
+
+ while (++index < length) {
+ assignFunc(result, props[index], index < valsLength ? values[index] : undefined);
+ }
+ return result;
+ }
+
+ /**
+ * Creates a clone of `buffer`.
+ *
+ * @private
+ * @param {Buffer} buffer The buffer to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Buffer} Returns the cloned buffer.
+ */
+ function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
var Ctor = buffer.constructor,
- result = new Ctor(buffer.byteLength),
+ result = new Ctor(buffer.length);
+
+ buffer.copy(result);
+ return result;
+ }
+
+ /**
+ * Creates a clone of `arrayBuffer`.
+ *
+ * @private
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+ function cloneArrayBuffer(arrayBuffer) {
+ var Ctor = arrayBuffer.constructor,
+ result = new Ctor(arrayBuffer.byteLength),
view = new Uint8Array(result);
- view.set(new Uint8Array(buffer));
+ view.set(new Uint8Array(arrayBuffer));
return result;
}
* @returns {Object} Returns the cloned symbol object.
*/
function cloneSymbol(symbol) {
- return _Symbol ? Object(symbolValueOf.call(symbol)) : {};
+ return Symbol ? Object(symbolValueOf.call(symbol)) : {};
}
/**
* @returns {Object} Returns the cloned typed array.
*/
function cloneTypedArray(typedArray, isDeep) {
- var buffer = typedArray.buffer,
+ var arrayBuffer = typedArray.buffer,
+ buffer = isDeep ? cloneArrayBuffer(arrayBuffer) : arrayBuffer,
Ctor = typedArray.constructor;
- return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, typedArray.byteOffset, typedArray.length);
+ return new Ctor(buffer, typedArray.byteOffset, typedArray.length);
}
/**
* @param {Array|Object} args The provided arguments.
* @param {Array} partials The arguments to prepend to those provided.
* @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
* @returns {Array} Returns the new array of composed arguments.
*/
- function composeArgs(args, partials, holders) {
- var holdersLength = holders.length,
- argsIndex = -1,
- argsLength = nativeMax(args.length - holdersLength, 0),
+ function composeArgs(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersLength = holders.length,
leftIndex = -1,
leftLength = partials.length,
- result = Array(leftLength + argsLength);
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(leftLength + rangeLength),
+ isUncurried = !isCurried;
while (++leftIndex < leftLength) {
result[leftIndex] = partials[leftIndex];
}
while (++argsIndex < holdersLength) {
- result[holders[argsIndex]] = args[argsIndex];
+ if (isUncurried || argsIndex < argsLength) {
+ result[holders[argsIndex]] = args[argsIndex];
+ }
}
- while (argsLength--) {
+ while (rangeLength--) {
result[leftIndex++] = args[argsIndex++];
}
return result;
* @param {Array|Object} args The provided arguments.
* @param {Array} partials The arguments to append to those provided.
* @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
* @returns {Array} Returns the new array of composed arguments.
*/
- function composeArgsRight(args, partials, holders) {
- var holdersIndex = -1,
+ function composeArgsRight(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersIndex = -1,
holdersLength = holders.length,
- argsIndex = -1,
- argsLength = nativeMax(args.length - holdersLength, 0),
rightIndex = -1,
rightLength = partials.length,
- result = Array(argsLength + rightLength);
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(rangeLength + rightLength),
+ isUncurried = !isCurried;
- while (++argsIndex < argsLength) {
+ while (++argsIndex < rangeLength) {
result[argsIndex] = args[argsIndex];
}
var offset = argsIndex;
result[offset + rightIndex] = partials[rightIndex];
}
while (++holdersIndex < holdersLength) {
- result[offset + holders[holdersIndex]] = args[argsIndex++];
+ if (isUncurried || argsIndex < argsLength) {
+ result[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
}
return result;
}
length = props.length;
while (++index < length) {
- var key = props[index],
- newValue = customizer ? customizer(object[key], source[key], key, object, source) : source[key];
+ var key = props[index];
+
+ var newValue = customizer
+ ? customizer(object[key], source[key], key, object, source)
+ : source[key];
assignValue(object, key, newValue);
}
* Creates a function like `_.groupBy`.
*
* @private
- * @param {Function} setter The function to set keys and values of the accumulator object.
- * @param {Function} [initializer] The function to initialize the accumulator object.
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} [initializer] The accumulator object initializer.
* @returns {Function} Returns the new aggregator function.
*/
function createAggregator(setter, initializer) {
return function(collection, iteratee) {
- var result = initializer ? initializer() : {};
- iteratee = getIteratee(iteratee);
+ var func = isArray(collection) ? arrayAggregator : baseAggregator,
+ accumulator = initializer ? initializer() : {};
- if (isArray(collection)) {
- var index = -1,
- length = collection.length;
-
- while (++index < length) {
- var value = collection[index];
- setter(result, value, iteratee(value), collection);
- }
- } else {
- baseEach(collection, function(value, key, collection) {
- setter(result, value, iteratee(value), collection);
- });
- }
- return result;
+ return func(collection, setter, getIteratee(iteratee), accumulator);
};
}
customizer = length > 1 ? sources[length - 1] : undefined,
guard = length > 2 ? sources[2] : undefined;
- customizer = typeof customizer == 'function' ? (length--, customizer) : undefined;
+ customizer = typeof customizer == 'function'
+ ? (length--, customizer)
+ : undefined;
+
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
customizer = length < 3 ? undefined : customizer;
length = 1;
while (++index < length) {
var source = sources[index];
if (source) {
- assigner(object, source, customizer);
+ assigner(object, source, index, customizer);
}
}
return object;
return function(string) {
string = toString(string);
- var strSymbols = reHasComplexSymbol.test(string) ? stringToArray(string) : undefined,
- chr = strSymbols ? strSymbols[0] : string.charAt(0),
+ var strSymbols = reHasComplexSymbol.test(string)
+ ? stringToArray(string)
+ : undefined;
+
+ var chr = strSymbols ? strSymbols[0] : string.charAt(0),
trailing = strSymbols ? strSymbols.slice(1).join('') : string.slice(1);
return chr[methodName]() + trailing;
function wrapper() {
var length = arguments.length,
- index = length,
args = Array(length),
- fn = (this && this !== root && this instanceof wrapper) ? Ctor : func,
- placeholder = wrapper.placeholder;
+ index = length,
+ placeholder = getPlaceholder(wrapper);
while (index--) {
args[index] = arguments[index];
: replaceHolders(args, placeholder);
length -= holders.length;
- return length < arity
- ? createRecurryWrapper(func, bitmask, createHybridWrapper, placeholder, undefined, args, holders, undefined, undefined, arity - length)
- : apply(fn, this, args);
+ if (length < arity) {
+ return createRecurryWrapper(
+ func, bitmask, createHybridWrapper, wrapper.placeholder, undefined,
+ args, holders, undefined, undefined, arity - length);
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return apply(fn, this, args);
}
return wrapper;
}
*/
function createFlow(fromRight) {
return rest(function(funcs) {
- funcs = baseFlatten(funcs);
+ funcs = baseFlatten(funcs, 1);
var length = funcs.length,
index = length,
var funcName = getFuncName(func),
data = funcName == 'wrapper' ? getData(func) : undefined;
- if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {
+ if (data && isLaziable(data[0]) &&
+ data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) &&
+ !data[4].length && data[9] == 1
+ ) {
wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
} else {
wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
var args = arguments,
value = args[0];
- if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
+ if (wrapper && args.length == 1 &&
+ isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
return wrapper.plant(value).value();
}
var index = 0,
var isAry = bitmask & ARY_FLAG,
isBind = bitmask & BIND_FLAG,
isBindKey = bitmask & BIND_KEY_FLAG,
- isCurry = bitmask & CURRY_FLAG,
- isCurryRight = bitmask & CURRY_RIGHT_FLAG,
+ isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
isFlip = bitmask & FLIP_FLAG,
Ctor = isBindKey ? undefined : createCtorWrapper(func);
while (index--) {
args[index] = arguments[index];
}
+ if (isCurried) {
+ var placeholder = getPlaceholder(wrapper),
+ holdersCount = countHolders(args, placeholder);
+ }
if (partials) {
- args = composeArgs(args, partials, holders);
+ args = composeArgs(args, partials, holders, isCurried);
}
if (partialsRight) {
- args = composeArgsRight(args, partialsRight, holdersRight);
+ args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
}
- if (isCurry || isCurryRight) {
- var placeholder = wrapper.placeholder,
- argsHolders = replaceHolders(args, placeholder);
-
- length -= argsHolders.length;
- if (length < arity) {
- return createRecurryWrapper(func, bitmask, createHybridWrapper, placeholder, thisArg, args, argsHolders, argPos, ary, arity - length);
- }
+ length -= holdersCount;
+ if (isCurried && length < arity) {
+ var newHolders = replaceHolders(args, placeholder);
+ return createRecurryWrapper(
+ func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg,
+ args, newHolders, argPos, ary, arity - length
+ );
}
var thisBinding = isBind ? thisArg : this,
fn = isBindKey ? thisBinding[func] : func;
+ length = args.length;
if (argPos) {
args = reorder(args, argPos);
- } else if (isFlip && args.length > 1) {
+ } else if (isFlip && length > 1) {
args.reverse();
}
- if (isAry && ary < args.length) {
+ if (isAry && ary < length) {
args.length = ary;
}
if (this && this !== root && this instanceof wrapper) {
}
/**
+ * Creates a function like `_.invertBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} toIteratee The function to resolve iteratees.
+ * @returns {Function} Returns the new inverter function.
+ */
+ function createInverter(setter, toIteratee) {
+ return function(object, iteratee) {
+ return baseInverter(object, setter, toIteratee(iteratee), {});
+ };
+ }
+
+ /**
* Creates a function like `_.over`.
*
* @private
*/
function createOver(arrayFunc) {
return rest(function(iteratees) {
- iteratees = arrayMap(baseFlatten(iteratees), getIteratee());
+ iteratees = arrayMap(baseFlatten(iteratees, 1), getIteratee());
return rest(function(args) {
var thisArg = this;
return arrayFunc(iteratees, function(iteratee) {
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
* @param {Function} wrapFunc The function to create the `func` wrapper.
- * @param {*} placeholder The placeholder to replace.
+ * @param {*} placeholder The placeholder value.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to prepend to those provided to the new function.
* @param {Array} [holders] The `partials` placeholder indexes.
function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
var isCurry = bitmask & CURRY_FLAG,
newArgPos = argPos ? copyArray(argPos) : undefined,
- newsHolders = isCurry ? holders : undefined,
+ newHolders = isCurry ? holders : undefined,
newHoldersRight = isCurry ? undefined : holders,
newPartials = isCurry ? partials : undefined,
newPartialsRight = isCurry ? undefined : partials;
if (!(bitmask & CURRY_BOUND_FLAG)) {
bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
}
- var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, arity],
- result = wrapFunc.apply(undefined, newData);
+ var newData = [
+ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
+ newHoldersRight, newArgPos, ary, arity
+ ];
+ var result = wrapFunc.apply(undefined, newData);
if (isLaziable(func)) {
setData(result, newData);
}
partials = holders = undefined;
}
- var data = isBindKey ? undefined : getData(func),
- newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
+ var data = isBindKey ? undefined : getData(func);
+
+ var newData = [
+ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
+ argPos, ary, arity
+ ];
if (data) {
mergeData(newData, data);
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;
}
*/
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),
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;
}
}
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],
}
/**
+ * Gets the argument placeholder value for `func`.
+ *
+ * @private
+ * @param {Function} func The function to inspect.
+ * @returns {*} Returns the placeholder value.
+ */
+ function getPlaceholder(func) {
+ var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
+ return object.placeholder;
+ }
+
+ /**
* Creates an array of the own symbol properties of `object`.
*
* @private
return objectToString.call(value);
}
- // Fallback for IE 11 providing `toStringTag` values for maps and sets.
- if ((Map && getTag(new Map) != mapTag) || (Set && getTag(new Set) != setTag)) {
+ // Fallback for IE 11 providing `toStringTag` values for maps, sets, and weakmaps.
+ if ((Map && getTag(new Map) != mapTag) ||
+ (Set && getTag(new Set) != setTag) ||
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
getTag = function(value) {
var result = objectToString.call(value),
Ctor = result == objectTag ? value.constructor : null,
ctorString = typeof Ctor == 'function' ? funcToString.call(Ctor) : '';
if (ctorString) {
- if (ctorString == mapCtorString) {
- return mapTag;
- }
- if (ctorString == setCtorString) {
- return setTag;
+ switch (ctorString) {
+ case mapCtorString: return mapTag;
+ case setCtorString: return setTag;
+ case weakMapCtorString: return weakMapTag;
}
}
return result;
}
var result = hasFunc(object, path);
if (!result && !isKey(path)) {
- path = baseToPath(path);
+ path = baseCastPath(path);
object = parent(object, path);
if (object != null) {
path = last(path);
result = hasFunc(object, path);
}
}
- return result || (isLength(object && object.length) && isIndex(path, object.length) &&
- (isArray(object) || isString(object) || isArguments(object)));
+ var length = object ? object.length : undefined;
+ return result || (
+ !!length && isLength(length) && isIndex(path, length) &&
+ (isArray(object) || isString(object) || isArguments(object))
+ );
}
/**
* @returns {Object} Returns the initialized clone.
*/
function initCloneObject(object) {
- var Ctor = object.constructor;
- return baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined);
+ return (isFunction(object.constructor) && !isPrototype(object))
+ ? baseCreate(getPrototypeOf(object))
+ : {};
}
/**
var Ctor = object.constructor;
switch (tag) {
case arrayBufferTag:
- return cloneBuffer(object);
+ return cloneArrayBuffer(object);
case boolTag:
case dateTag:
*/
function indexKeys(object) {
var length = object ? object.length : undefined;
- return (isLength(length) && (isArray(object) || isString(object) || isArguments(object)))
- ? baseTimes(length, String)
- : null;
+ if (isLength(length) &&
+ (isArray(object) || isString(object) || isArguments(object))) {
+ return baseTimes(length, String);
+ }
+ return null;
}
/**
- * Checks if the provided arguments are from an iteratee call.
+ * Checks if the given arguments are from an iteratee call.
*
* @private
* @param {*} value The potential iteratee value argument.
function isKeyable(value) {
var type = typeof value;
return type == 'number' || type == 'boolean' ||
- (type == 'string' && value !== '__proto__') || value == null;
+ (type == 'string' && value != '__proto__') || value == null;
}
/**
*/
function isPrototype(value) {
var Ctor = value && value.constructor,
- proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+ proto = (isFunction(Ctor) && Ctor.prototype) || objectProto;
return value === proto;
}
isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG);
var isCombo =
- (srcBitmask == ARY_FLAG && (bitmask == CURRY_FLAG)) ||
- (srcBitmask == ARY_FLAG && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) ||
- (srcBitmask == (ARY_FLAG | REARG_FLAG) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG));
+ ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) ||
+ ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) ||
+ ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG));
// Exit early if metadata can't be merged.
if (!(isCommon || isCombo)) {
if (srcBitmask & BIND_FLAG) {
data[2] = source[2];
// Set when currying a bound function.
- newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
+ newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG;
}
// Compose partial arguments.
var value = source[3];
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;
}
/**
}
/**
- * Converts `value` to an array-like object if it's not one.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {Array} Returns the array-like object.
- */
- function toArrayLikeObject(value) {
- return isArrayLikeObject(value) ? value : [];
- }
-
- /**
- * 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
* // => [1]
*/
var concat = rest(function(array, values) {
- values = baseFlatten(values);
- return arrayConcat(isArray(array) ? array : [Object(array)], values);
+ if (!isArray(array)) {
+ array = array == null ? [] : [Object(array)];
+ }
+ values = baseFlatten(values, 1);
+ return arrayConcat(array, values);
});
/**
* Creates an array of unique `array` values not included in the other
- * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * given arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
* @static
*/
var difference = rest(function(array, values) {
return isArrayLikeObject(array)
- ? baseDifference(array, baseFlatten(values, false, true))
+ ? baseDifference(array, baseFlatten(values, 1, true))
: [];
});
* _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
* // => [3.1, 1.3]
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
iteratee = undefined;
}
return isArrayLikeObject(array)
- ? baseDifference(array, baseFlatten(values, false, true), getIteratee(iteratee))
+ ? baseDifference(array, baseFlatten(values, 1, true), getIteratee(iteratee))
: [];
});
comparator = undefined;
}
return isArrayLikeObject(array)
- ? baseDifference(array, baseFlatten(values, false, true), undefined, comparator)
+ ? baseDifference(array, baseFlatten(values, 1, true), undefined, comparator)
: [];
});
* _.dropRightWhile(users, function(o) { return !o.active; });
* // => objects for ['barney']
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
* // => objects for ['barney', 'fred']
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.dropRightWhile(users, ['active', false]);
* // => objects for ['barney']
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.dropRightWhile(users, 'active');
* // => objects for ['barney', 'fred', 'pebbles']
*/
* _.dropWhile(users, function(o) { return !o.active; });
* // => objects for ['pebbles']
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.dropWhile(users, { 'user': 'barney', 'active': false });
* // => objects for ['fred', 'pebbles']
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.dropWhile(users, ['active', false]);
* // => objects for ['pebbles']
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.dropWhile(users, 'active');
* // => objects for ['barney', 'fred', 'pebbles']
*/
* _.findIndex(users, function(o) { return o.user == 'barney'; });
* // => 0
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.findIndex(users, { 'user': 'fred', 'active': false });
* // => 1
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.findIndex(users, ['active', false]);
* // => 0
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.findIndex(users, 'active');
* // => 2
*/
* _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
* // => 2
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.findLastIndex(users, { 'user': 'barney', 'active': true });
* // => 0
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.findLastIndex(users, ['active', false]);
* // => 2
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.findLastIndex(users, 'active');
* // => 0
*/
}
/**
- * Creates an array of flattened values by running each element in `array`
- * through `iteratee` and concating its result to the other mapped values.
- * The iteratee is invoked with three arguments: (value, index|key, array).
+ * Flattens `array` a single level deep.
*
* @static
* @memberOf _
* @category Array
- * @param {Array} array The array to iterate over.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
- * @returns {Array} Returns the new array.
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
* @example
*
- * function duplicate(n) {
- * return [n, n];
- * }
- *
- * _.flatMap([1, 2], duplicate);
- * // => [1, 1, 2, 2]
+ * _.flatten([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, [3, [4]], 5]
*/
- function flatMap(array, iteratee) {
+ function flatten(array) {
var length = array ? array.length : 0;
- return length ? baseFlatten(arrayMap(array, getIteratee(iteratee, 3))) : [];
+ return length ? baseFlatten(array, 1) : [];
}
/**
- * Flattens `array` a single level.
+ * Recursively flattens `array`.
*
* @static
* @memberOf _
* @returns {Array} Returns the new flattened array.
* @example
*
- * _.flatten([1, [2, 3, [4]]]);
- * // => [1, 2, 3, [4]]
+ * _.flattenDeep([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, 3, 4, 5]
*/
- function flatten(array) {
+ function flattenDeep(array) {
var length = array ? array.length : 0;
- return length ? baseFlatten(array) : [];
+ return length ? baseFlatten(array, INFINITY) : [];
}
/**
- * This method is like `_.flatten` except that it recursively flattens `array`.
+ * Recursively flatten `array` up to `depth` times.
*
* @static
* @memberOf _
* @category Array
- * @param {Array} array The array to recursively flatten.
+ * @param {Array} array The array to flatten.
+ * @param {number} [depth=1] The maximum recursion depth.
* @returns {Array} Returns the new flattened array.
* @example
*
- * _.flattenDeep([1, [2, 3, [4]]]);
- * // => [1, 2, 3, 4]
+ * var array = [1, [2, [3, [4]], 5]];
+ *
+ * _.flattenDepth(array, 1);
+ * // => [1, 2, [3, [4]], 5]
+ *
+ * _.flattenDepth(array, 2);
+ * // => [1, 2, 3, [4], 5]
*/
- function flattenDeep(array) {
+ function flattenDepth(array, depth) {
var length = array ? array.length : 0;
- return length ? baseFlatten(array, true) : [];
+ if (!length) {
+ return [];
+ }
+ depth = depth === undefined ? 1 : toInteger(depth);
+ return baseFlatten(array, depth);
}
/**
while (++index < length) {
var pair = pairs[index];
- baseSet(result, pair[0], pair[1]);
+ result[pair[0]] = pair[1];
}
return result;
}
* 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.
+ * from the end of `array`.
*
* @static
* @memberOf _
* _.indexOf([1, 2, 1, 2], 2);
* // => 1
*
- * // using `fromIndex`
+ * // Search from the `fromIndex`.
* _.indexOf([1, 2, 1, 2], 2, 2);
* // => 3
*/
}
/**
- * Creates an array of unique values that are included in all of the provided
- * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * Creates an array of unique values that are included in all given arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
* @static
* @param {...Array} [arrays] The arrays to inspect.
* @returns {Array} Returns the new array of shared values.
* @example
+ *
* _.intersection([2, 1], [4, 2], [1, 2]);
* // => [2]
*/
var intersection = rest(function(arrays) {
- var mapped = arrayMap(arrays, toArrayLikeObject);
+ var mapped = arrayMap(arrays, baseCastArrayLikeObject);
return (mapped.length && mapped[0] === arrays[0])
? baseIntersection(mapped)
: [];
* _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
* // => [2.1]
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }]
*/
var intersectionBy = rest(function(arrays) {
var iteratee = last(arrays),
- mapped = arrayMap(arrays, toArrayLikeObject);
+ mapped = arrayMap(arrays, baseCastArrayLikeObject);
if (iteratee === last(mapped)) {
iteratee = undefined;
*/
var intersectionWith = rest(function(arrays) {
var comparator = last(arrays),
- mapped = arrayMap(arrays, toArrayLikeObject);
+ mapped = arrayMap(arrays, baseCastArrayLikeObject);
if (comparator === last(mapped)) {
comparator = undefined;
* _.lastIndexOf([1, 2, 1, 2], 2);
* // => 3
*
- * // using `fromIndex`
+ * // Search from the `fromIndex`.
* _.lastIndexOf([1, 2, 1, 2], 2, 2);
* // => 1
*/
}
/**
- * Removes all provided values from `array` using
+ * Removes all given values from `array` using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
- * **Note:** Unlike `_.without`, this method mutates `array`.
+ * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
+ * to remove elements from an array by predicate.
*
* @static
* @memberOf _
*
* var array = [1, 2, 3, 1, 2, 3];
*
- * _.pull(array, [2, 3]);
+ * _.pullAll(array, [2, 3]);
* console.log(array);
* // => [1, 1]
*/
/**
* This method is like `_.pullAll` except that it accepts `iteratee` which is
- * invoked for each element of `array` and `values` to to generate the criterion
+ * invoked for each element of `array` and `values` to generate the criterion
* by which uniqueness is computed. The iteratee is invoked with one argument: (value).
*
* **Note:** Unlike `_.differenceBy`, this method mutates `array`.
* // => [10, 20]
*/
var pullAt = rest(function(array, indexes) {
- indexes = arrayMap(baseFlatten(indexes), String);
+ indexes = arrayMap(baseFlatten(indexes, 1), String);
var result = baseAt(array, indexes);
basePullAt(array, indexes.sort(compareAscending));
/**
* Removes all elements from `array` that `predicate` returns truthy for
- * and returns an array of the removed elements. The predicate is invoked with
- * three arguments: (value, index, array).
+ * and returns an array of the removed elements. The predicate is invoked
+ * with three arguments: (value, index, array).
*
- * **Note:** Unlike `_.filter`, this method mutates `array`.
+ * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
+ * to pull elements from an array by value.
*
* @static
* @memberOf _
* **Note:** This method mutates `array` and is based on
* [`Array#reverse`](https://mdn.io/Array/reverse).
*
+ * @static
* @memberOf _
* @category Array
* @returns {Array} Returns `array`.
* _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict));
* // => 1
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
* // => 0
*/
* @returns {number} Returns the index at which `value` should be inserted into `array`.
* @example
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
* // => 1
*/
* @example
*
* _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
- * // => [1.1, 2.2]
+ * // => [1.1, 2.3]
*/
function sortedUniqBy(array, iteratee) {
return (array && array.length)
* _.takeRightWhile(users, function(o) { return !o.active; });
* // => objects for ['fred', 'pebbles']
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
* // => objects for ['pebbles']
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.takeRightWhile(users, ['active', false]);
* // => objects for ['fred', 'pebbles']
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.takeRightWhile(users, 'active');
* // => []
*/
* _.takeWhile(users, function(o) { return !o.active; });
* // => objects for ['barney', 'fred']
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.takeWhile(users, { 'user': 'barney', 'active': false });
* // => objects for ['barney']
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.takeWhile(users, ['active', false]);
* // => objects for ['barney', 'fred']
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.takeWhile(users, 'active');
* // => []
*/
}
/**
- * Creates an array of unique values, in order, from all of the provided arrays
- * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * Creates an array of unique values, in order, from all given arrays using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
* @static
* // => [2, 1, 4]
*/
var union = rest(function(arrays) {
- return baseUniq(baseFlatten(arrays, false, true));
+ return baseUniq(baseFlatten(arrays, 1, true));
});
/**
* _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
* // => [2.1, 1.2, 4.3]
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
if (isArrayLikeObject(iteratee)) {
iteratee = undefined;
}
- return baseUniq(baseFlatten(arrays, false, true), getIteratee(iteratee));
+ return baseUniq(baseFlatten(arrays, 1, true), getIteratee(iteratee));
});
/**
if (isArrayLikeObject(comparator)) {
comparator = undefined;
}
- return baseUniq(baseFlatten(arrays, false, true), undefined, comparator);
+ return baseUniq(baseFlatten(arrays, 1, true), undefined, comparator);
});
/**
* _.uniqBy([2.1, 1.2, 2.3], Math.floor);
* // => [2.1, 1.2]
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
}
/**
- * Creates an array excluding all provided values using
+ * Creates an array excluding all given values using
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
* for equality comparisons.
*
/**
* Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
- * of the provided arrays.
+ * of the given arrays.
*
* @static
* @memberOf _
* _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor);
* // => [1.2, 4.3]
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
* @returns {Object} Returns the new object.
* @example
*
- * _.zipObject(['fred', 'barney'], [30, 40]);
- * // => { 'fred': 30, 'barney': 40 }
+ * _.zipObject(['a', 'b'], [1, 2]);
+ * // => { 'a': 1, 'b': 2 }
*/
function zipObject(props, values) {
- var index = -1,
- length = props ? props.length : 0,
- valsLength = values ? values.length : 0,
- result = {};
+ return baseZipObject(props || [], values || [], assignValue);
+ }
- while (++index < length) {
- baseSet(result, props[index], index < valsLength ? values[index] : undefined);
- }
- return result;
+ /**
+ * This method is like `_.zipObject` except that it supports property paths.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} [props=[]] The property names.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
+ * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
+ */
+ function zipObjectDeep(props, values) {
+ return baseZipObject(props || [], values || [], baseSet);
}
/**
}
/**
- * 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.
+ * 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 modify intermediate results.
*
* @static
* @memberOf _
*
* _([1, 2, 3])
* .tap(function(array) {
+ * // Mutate input array.
* array.pop();
* })
* .reverse()
/**
* This method is like `_.tap` except that it returns the result of `interceptor`.
+ * The purpose of this method is to "pass thru" values replacing intermediate
+ * results in a method chain.
*
* @static
* @memberOf _
* // => ['a', 'c']
*/
var wrapperAt = rest(function(paths) {
- paths = baseFlatten(paths);
+ paths = baseFlatten(paths, 1);
var length = paths.length,
start = length ? paths[0] : 0,
value = this.__wrapped__,
interceptor = function(object) { return baseAt(object, paths); };
- if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
+ if (length > 1 || this.__actions__.length ||
+ !(value instanceof LazyWrapper) || !isIndex(start)) {
return this.thru(interceptor);
}
value = value.slice(start, +start + (length ? 1 : 0));
- value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
+ value.__actions__.push({
+ 'func': thru,
+ 'args': [interceptor],
+ 'thisArg': undefined
+ });
return new LodashWrapper(value, this.__chain__).thru(function(array) {
if (length && !array.length) {
array.push(undefined);
* { 'user': 'fred', 'age': 40 }
* ];
*
- * // without explicit chaining
+ * // A sequence without explicit chaining.
* _(users).head();
* // => { 'user': 'barney', 'age': 36 }
*
- * // with explicit chaining
+ * // A sequence with explicit chaining.
* _(users)
* .chain()
* .head()
/**
* 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.
wrapped = new LazyWrapper(this);
}
wrapped = wrapped.reverse();
- wrapped.__actions__.push({ 'func': thru, 'args': [reverse], 'thisArg': undefined });
+ wrapped.__actions__.push({
+ 'func': thru,
+ 'args': [reverse],
+ 'thisArg': undefined
+ });
return new LodashWrapper(wrapped, this.__chain__);
}
return this.thru(reverse);
*
* @name value
* @memberOf _
- * @alias run, toJSON, valueOf
+ * @alias toJSON, valueOf
* @category Seq
* @returns {*} Returns the resolved unwrapped value.
* @example
* @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
*
* { 'user': 'fred', 'active': false }
* ];
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.every(users, { 'user': 'barney', 'active': false });
* // => false
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.every(users, ['active', false]);
* // => true
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.every(users, 'active');
* // => false
*/
* _.filter(users, function(o) { return !o.active; });
* // => objects for ['fred']
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.filter(users, { 'age': 36, 'active': true });
* // => objects for ['barney']
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.filter(users, ['active', false]);
* // => objects for ['fred']
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.filter(users, 'active');
* // => objects for ['barney']
*/
* _.find(users, function(o) { return o.age < 40; });
* // => object for 'barney'
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.find(users, { 'age': 1, 'active': true });
* // => object for 'pebbles'
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.find(users, ['active', false]);
* // => object for 'fred'
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.find(users, 'active');
* // => object for 'barney'
*/
}
/**
+ * Creates an array of flattened values by running each element in `collection`
+ * through `iteratee` and concating its result to the other mapped values.
+ * The iteratee 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} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [n, n];
+ * }
+ *
+ * _.flatMap([1, 2], duplicate);
+ * // => [1, 1, 2, 2]
+ */
+ function flatMap(collection, iteratee) {
+ return baseFlatten(map(collection, iteratee), 1);
+ }
+
+ /**
* 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`.
function forEach(collection, iteratee) {
return (typeof iteratee == 'function' && isArray(collection))
? arrayEach(collection, iteratee)
- : baseEach(collection, toFunction(iteratee));
+ : baseEach(collection, baseCastFunction(iteratee));
}
/**
function forEachRight(collection, iteratee) {
return (typeof iteratee == 'function' && isArray(collection))
? arrayEachRight(collection, iteratee)
- : baseEachRight(collection, toFunction(iteratee));
+ : baseEachRight(collection, baseCastFunction(iteratee));
}
/**
* 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
*
* _.groupBy([6.1, 4.2, 6.3], Math.floor);
* // => { '4': [4.2], '6': [6.1, 6.3] }
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
* @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
*
- * var keyData = [
+ * var array = [
* { 'dir': 'left', 'code': 97 },
* { 'dir': 'right', 'code': 100 }
* ];
*
- * _.keyBy(keyData, 'dir');
- * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
- *
- * _.keyBy(keyData, function(o) {
+ * _.keyBy(array, function(o) {
* return String.fromCharCode(o.code);
* });
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.keyBy(array, 'dir');
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
*/
var keyBy = createAggregator(function(result, value, key) {
result[key] = value;
* 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' },
* { 'user': 'fred' }
* ];
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.map(users, 'user');
* // => ['barney', 'fred']
*/
* { 'user': 'barney', 'age': 36 }
* ];
*
- * // sort by `user` in ascending order and by `age` in descending order
+ * // Sort by `user` in ascending order and by `age` in descending order.
* _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
*/
/**
* 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 _
* _.partition(users, function(o) { return o.active; });
* // => objects for [['fred'], ['barney', 'pebbles']]
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.partition(users, { 'age': 1, 'active': false });
* // => objects for [['pebbles'], ['barney', 'fred']]
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.partition(users, ['active', false]);
* // => objects for [['barney', 'pebbles'], ['fred']]
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.partition(users, 'active');
* // => objects for [['fred'], ['barney', 'pebbles']]
*/
* 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
+ * is not given the first element of `collection` is used as the initial
* value. The iteratee is invoked with four arguments:
* (accumulator, value, index|key, collection).
*
*
* _.reduce([1, 2], function(sum, n) {
* return sum + n;
- * });
+ * }, 0);
* // => 3
*
* _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
*/
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);
}
/**
*/
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);
}
/**
* _.reject(users, function(o) { return !o.active; });
* // => objects for ['fred']
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.reject(users, { 'age': 40, 'active': true });
* // => objects for ['barney']
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.reject(users, ['active', false]);
* // => objects for ['fred']
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.reject(users, 'active');
* // => objects for ['barney']
*/
}
/**
- * Gets `n` random elements from `collection`.
+ * Gets `n` random elements at unique keys from `collection` up to the
+ * size of `collection`.
*
* @static
* @memberOf _
* @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,
* { 'user': 'fred', 'active': false }
* ];
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.some(users, { 'user': 'barney', 'active': false });
* // => false
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.some(users, ['active', false]);
* // => true
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.some(users, 'active');
* // => true
*/
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
iteratees.length = 1;
}
- return baseOrderBy(collection, baseFlatten(iteratees), []);
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
});
/*------------------------------------------------------------------------*/
*
* @static
* @memberOf _
- * @type Function
+ * @type {Function}
* @category Date
* @returns {number} Returns the timestamp.
* @example
* bound('!');
* // => 'hi fred!'
*
- * // using placeholders
+ * // Bound with placeholders.
* var bound = _.bind(greet, object, _, '!');
* bound('hi');
* // => 'hi fred!'
var bind = rest(function(func, thisArg, partials) {
var bitmask = BIND_FLAG;
if (partials.length) {
- var holders = replaceHolders(partials, bind.placeholder);
+ var holders = replaceHolders(partials, getPlaceholder(bind));
bitmask |= PARTIAL_FLAG;
}
return createWrapper(func, bitmask, thisArg, partials, holders);
* bound('!');
* // => 'hiya fred!'
*
- * // using placeholders
+ * // Bound with placeholders.
* var bound = _.bindKey(object, 'greet', _, '!');
* bound('hi');
* // => 'hiya fred!'
var bindKey = rest(function(object, key, partials) {
var bitmask = BIND_FLAG | BIND_KEY_FLAG;
if (partials.length) {
- var holders = replaceHolders(partials, bindKey.placeholder);
+ var holders = replaceHolders(partials, getPlaceholder(bindKey));
bitmask |= PARTIAL_FLAG;
}
return createWrapper(key, bitmask, object, partials, holders);
* curried(1, 2, 3);
* // => [1, 2, 3]
*
- * // using placeholders
+ * // Curried with placeholders.
* curried(1)(_, 3)(2);
* // => [1, 2, 3]
*/
* curried(1, 2, 3);
* // => [1, 2, 3]
*
- * // using placeholders
+ * // Curried with placeholders.
* curried(3)(1, _)(2);
* // => [1, 2, 3]
*/
* to the debounced function return the result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
- * on the trailing edge of the timeout only if the the debounced function is
+ * on the trailing edge of the timeout only if the debounced function is
* invoked more than once during the `wait` timeout.
*
* See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
* @returns {Function} Returns the new debounced function.
* @example
*
- * // avoid costly calculations while the window size is in flux
+ * // Avoid costly calculations while the window size is in flux.
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
*
- * // invoke `sendMail` when clicked, debouncing subsequent calls
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
* jQuery(element).on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* }));
*
- * // ensure `batchLog` is invoked once after 1 second of debounced calls
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
* var source = new EventSource('/stream');
* jQuery(source).on('message', debounced);
*
- * // cancel a trailing debounced invocation
+ * // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce(func, wait, options) {
if (maxWait === false) {
var leadingCall = leading && !timeoutId;
} else {
- if (!maxTimeoutId && !leading) {
+ if (!lastCalled && !maxTimeoutId && !leading) {
lastCalled = stamp;
}
- var remaining = maxWait - (stamp - lastCalled),
- isCalled = remaining <= 0 || remaining > maxWait;
+ var remaining = maxWait - (stamp - lastCalled);
+
+ var isCalled = (remaining <= 0 || remaining > maxWait) &&
+ (leading || maxTimeoutId);
if (isCalled) {
if (maxTimeoutId) {
* _.defer(function(text) {
* console.log(text);
* }, 'deferred');
- * // logs 'deferred' after one or more milliseconds
+ * // => logs 'deferred' after one or more milliseconds
*/
var defer = rest(function(func, args) {
return baseDelay(func, 1, args);
* values(object);
* // => [1, 2]
*
- * // modifying the result cache
+ * // Modify the result cache.
* values.cache.set(object, ['a', 'b']);
* values(object);
* // => ['a', 'b']
*
- * // replacing `_.memoize.Cache`
+ * // Replace `_.memoize.Cache`.
* _.memoize.Cache = WeakMap;
*/
function memoize(func, resolver) {
* // => [100, 10]
*/
var overArgs = rest(function(func, transforms) {
- transforms = arrayMap(baseFlatten(transforms), getIteratee());
+ transforms = arrayMap(baseFlatten(transforms, 1), getIteratee());
var funcsLength = transforms.length;
return rest(function(args) {
* sayHelloTo('fred');
* // => 'hello fred'
*
- * // using placeholders
+ * // Partially applied with placeholders.
* var greetFred = _.partial(greet, _, 'fred');
* greetFred('hi');
* // => 'hi fred'
*/
var partial = rest(function(func, partials) {
- var holders = replaceHolders(partials, partial.placeholder);
+ var holders = replaceHolders(partials, getPlaceholder(partial));
return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders);
});
* greetFred('hi');
* // => 'hi fred'
*
- * // using placeholders
+ * // Partially applied with placeholders.
* var sayHelloTo = _.partialRight(greet, 'hello', _);
* sayHelloTo('fred');
* // => 'hello fred'
*/
var partialRight = rest(function(func, partials) {
- var holders = replaceHolders(partials, partialRight.placeholder);
+ var holders = replaceHolders(partials, getPlaceholder(partialRight));
return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders);
});
* // => ['a', 'b', 'c']
*/
var rearg = rest(function(func, indexes) {
- return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes));
+ return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1));
});
/**
* @memberOf _
* @category Function
* @param {Function} func The function to spread arguments over.
+ * @param {number} [start=0] The start position of the spread.
* @returns {Function} Returns the new function.
* @example
*
* say(['fred', 'hello']);
* // => 'fred says hello'
*
- * // with a Promise
* var numbers = Promise.all([
* Promise.resolve(40),
* Promise.resolve(36)
* }));
* // => a Promise of 76
*/
- function spread(func) {
+ function spread(func, start) {
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
- return function(array) {
- return apply(func, this, array);
- };
+ start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
+ return rest(function(args) {
+ var array = args[start],
+ otherArgs = args.slice(0, start);
+
+ if (array) {
+ arrayPush(otherArgs, array);
+ }
+ return apply(func, this, otherArgs);
+ });
}
/**
* result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
- * on the trailing edge of the timeout only if the the throttled function is
+ * on the trailing edge of the timeout only if the throttled function is
* invoked more than once during the `wait` timeout.
*
* See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
* @returns {Function} Returns the new throttled function.
* @example
*
- * // avoid excessively updating the position while scrolling
+ * // Avoid excessively updating the position while scrolling.
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
*
- * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
+ * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
* jQuery(element).on('click', throttled);
*
- * // cancel a trailing throttled invocation
+ * // Cancel the trailing throttled invocation.
* jQuery(window).on('popstate', throttled.cancel);
*/
function throttle(func, wait, options) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
- return debounce(func, wait, { 'leading': leading, 'maxWait': wait, 'trailing': trailing });
+ return debounce(func, wait, {
+ 'leading': leading,
+ 'maxWait': wait,
+ 'trailing': trailing
+ });
}
/**
* @memberOf _
* @category Function
* @param {*} value The value to wrap.
- * @param {Function} wrapper The wrapper function.
+ * @param {Function} [wrapper=identity] The wrapper function.
* @returns {Function} Returns the new function.
* @example
*
/*------------------------------------------------------------------------*/
/**
+ * Casts `value` as an array if it's not one.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the cast array.
+ * @example
+ *
+ * _.castArray(1);
+ * // => [1]
+ *
+ * _.castArray({ 'a': 1 });
+ * // => [{ 'a': 1 }]
+ *
+ * _.castArray('abc');
+ * // => ['abc']
+ *
+ * _.castArray(null);
+ * // => [null]
+ *
+ * _.castArray(undefined);
+ * // => [undefined]
+ *
+ * _.castArray();
+ * // => []
+ *
+ * var array = [1, 2, 3];
+ * console.log(_.castArray(array) === array);
+ * // => true
+ */
+ function castArray() {
+ if (!arguments.length) {
+ return [];
+ }
+ var value = arguments[0];
+ return isArray(value) ? value : [value];
+ }
+
+ /**
* Creates a shallow clone of `value`.
*
* **Note:** This method is loosely based on the
* 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 _
* }
* }
*
- * var el = _.clone(document.body, customizer);
+ * var el = _.cloneWith(document.body, customizer);
*
* console.log(el === document.body);
* // => false
* }
* }
*
- * var el = _.cloneDeep(document.body, customizer);
+ * var el = _.cloneDeepWith(document.body, customizer);
*
* console.log(el === document.body);
* // => false
*
* @static
* @memberOf _
- * @type Function
+ * @type {Function}
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
var isArray = Array.isArray;
/**
+ * Checks if `value` is classified as an `ArrayBuffer` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArrayBuffer(new ArrayBuffer(2));
+ * // => true
+ *
+ * _.isArrayBuffer(new Array(2));
+ * // => false
+ */
+ function isArrayBuffer(value) {
+ return isObjectLike(value) && objectToString.call(value) == arrayBufferTag;
+ }
+
+ /**
* 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`.
*
* @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`.
}
/**
+ * Checks if `value` is a buffer.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
+ * @example
+ *
+ * _.isBuffer(new Buffer(2));
+ * // => true
+ *
+ * _.isBuffer(new Uint8Array(2));
+ * // => false
+ */
+ var isBuffer = !Buffer ? constant(false) : function(value) {
+ return value instanceof Buffer;
+ };
+
+ /**
* Checks if `value` is classified as a `Date` object.
*
* @static
* // => false
*/
function isEmpty(value) {
- return (!isObjectLike(value) || isFunction(value.splice))
- ? !size(value)
- : !keys(value).length;
+ if (isArrayLike(value) &&
+ (isArray(value) || isString(value) ||
+ isFunction(value.splice) || isArguments(value))) {
+ return !value.length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
}
/**
}
/**
- * This method is like `_.isEqual` except that it accepts `customizer` which is
- * invoked to compare values. If `customizer` returns `undefined` comparisons are
- * handled by the method instead. The `customizer` is invoked with up to seven arguments:
- * (objValue, othValue [, index|key, object, other, stack]).
+ * 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
+ * six arguments: (objValue, othValue [, index|key, object, other, stack]).
*
* @static
* @memberOf _
* // => false
*/
function isError(value) {
- return isObjectLike(value) &&
- typeof value.message == 'string' && objectToString.call(value) == errorTag;
+ if (!isObjectLike(value)) {
+ return false;
+ }
+ return (objectToString.call(value) == errorTag) ||
+ (typeof value.message == 'string' && typeof value.name == 'string');
}
/**
* // => false
*/
function isLength(value) {
- return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}
/**
* // => 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');
}
}
/**
- * Performs a deep comparison between `object` and `source` to determine if
- * `object` contains equivalent property values.
+ * Checks if `value` is classified as a `Map` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isMap(new Map);
+ * // => true
+ *
+ * _.isMap(new WeakMap);
+ * // => false
+ */
+ function isMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+ }
+
+ /**
+ * Performs a partial deep comparison between `object` and `source` to
+ * determine if `object` contains equivalent property values. This method is
+ * equivalent to a `_.matches` function when `source` is partially applied.
*
* **Note:** This method supports comparing the same values as `_.isEqual`.
*
/**
* 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
* // => true
*/
function isPlainObject(value) {
- if (!isObjectLike(value) || objectToString.call(value) != objectTag || isHostObject(value)) {
+ if (!isObjectLike(value) ||
+ objectToString.call(value) != objectTag || isHostObject(value)) {
return false;
}
- var proto = objectProto;
- if (typeof value.constructor == 'function') {
- proto = getPrototypeOf(value);
- }
+ var proto = getPrototypeOf(value);
if (proto === null) {
return true;
}
}
/**
+ * Checks if `value` is classified as a `Set` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isSet(new Set);
+ * // => true
+ *
+ * _.isSet(new WeakSet);
+ * // => false
+ */
+ function isSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+ }
+
+ /**
* Checks if `value` is classified as a `String` primitive or object.
*
* @static
* // => false
*/
function isTypedArray(value) {
- return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
+ return isObjectLike(value) &&
+ isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
}
/**
}
/**
+ * Checks if `value` is classified as a `WeakMap` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isWeakMap(new WeakMap);
+ * // => true
+ *
+ * _.isWeakMap(new Map);
+ * // => false
+ */
+ function isWeakMap(value) {
+ return isObjectLike(value) && getTag(value) == weakMapTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakSet` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isWeakSet(new WeakSet);
+ * // => true
+ *
+ * _.isWeakSet(new Set);
+ * // => false
+ */
+ function isWeakSet(value) {
+ return isObjectLike(value) && objectToString.call(value) == weakSetTag;
+ }
+
+ /**
* Checks if `value` is less than `other`.
*
* @static
* @memberOf _
* @category Lang
* @param {*} value The value to convert.
- * @return {number} Returns the converted integer.
+ * @returns {number} Returns the converted integer.
* @example
*
* _.toLength(3);
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;
* 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);
});
* 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);
});
* // => ['a', 'c']
*/
var at = rest(function(object, paths) {
- return baseAt(object, baseFlatten(paths));
+ return baseAt(object, baseFlatten(paths, 1));
});
/**
* 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.
+ * object is given its own enumerable properties are assigned to the created object.
*
* @static
* @memberOf _
* _.findKey(users, function(o) { return o.age < 40; });
* // => 'barney' (iteration order is not guaranteed)
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.findKey(users, { 'age': 1, 'active': true });
* // => 'pebbles'
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.findKey(users, ['active', false]);
* // => 'fred'
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.findKey(users, 'active');
* // => 'barney'
*/
* _.findLastKey(users, function(o) { return o.age < 40; });
* // => returns 'pebbles' assuming `_.findKey` returns 'barney'
*
- * // using the `_.matches` iteratee shorthand
+ * // The `_.matches` iteratee shorthand.
* _.findLastKey(users, { 'age': 36, 'active': true });
* // => 'barney'
*
- * // using the `_.matchesProperty` iteratee shorthand
+ * // The `_.matchesProperty` iteratee shorthand.
* _.findLastKey(users, ['active', false]);
* // => 'fred'
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.findLastKey(users, 'active');
* // => 'pebbles'
*/
* // => logs 'a', 'b', then 'c' (iteration order is not guaranteed)
*/
function forIn(object, iteratee) {
- return object == null ? object : baseFor(object, toFunction(iteratee), keysIn);
+ return object == null
+ ? object
+ : baseFor(object, baseCastFunction(iteratee), keysIn);
}
/**
* // => logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'
*/
function forInRight(object, iteratee) {
- return object == null ? object : baseForRight(object, toFunction(iteratee), keysIn);
+ return object == null
+ ? object
+ : baseForRight(object, baseCastFunction(iteratee), keysIn);
}
/**
* // => logs 'a' then 'b' (iteration order is not guaranteed)
*/
function forOwn(object, iteratee) {
- return object && baseForOwn(object, toFunction(iteratee));
+ return object && baseForOwn(object, baseCastFunction(iteratee));
}
/**
* // => logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'
*/
function forOwnRight(object, iteratee) {
- return object && baseForOwnRight(object, toFunction(iteratee));
+ return object && baseForOwnRight(object, baseCastFunction(iteratee));
}
/**
/**
* Creates an object composed of the inverted keys and values of `object`.
* If `object` contains duplicate values, subsequent values overwrite property
- * assignments of previous values unless `multiVal` is `true`.
+ * assignments of previous values.
*
* @static
* @memberOf _
* @category Object
* @param {Object} object The object to invert.
- * @param {boolean} [multiVal] Allow multiple values per key.
- * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
* @returns {Object} Returns the new inverted object.
* @example
*
*
* _.invert(object);
* // => { '1': 'c', '2': 'b' }
+ */
+ var invert = createInverter(function(result, value, key) {
+ result[value] = key;
+ }, constant(identity));
+
+ /**
+ * This method is like `_.invert` except that the inverted object is generated
+ * from the results of running each element of `object` through `iteratee`.
+ * The corresponding inverted value of each inverted key is an array of keys
+ * responsible for generating the inverted value. The iteratee is invoked
+ * with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Object} Returns the new inverted object.
+ * @example
*
- * // with `multiVal`
- * _.invert(object, true);
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invertBy(object);
* // => { '1': ['a', 'c'], '2': ['b'] }
+ *
+ * _.invertBy(object, function(value) {
+ * return 'group' + value;
+ * });
+ * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
*/
- function invert(object, multiVal, guard) {
- return arrayReduce(keys(object), function(result, key) {
- var value = object[key];
- if (multiVal && !guard) {
- if (hasOwnProperty.call(result, value)) {
- result[value].push(key);
- } else {
- result[value] = [key];
- }
- }
- else {
- result[value] = key;
- }
- return result;
- }, {});
- }
+ var invertBy = createInverter(function(result, value, key) {
+ if (hasOwnProperty.call(result, value)) {
+ result[value].push(key);
+ } else {
+ result[value] = [key];
+ }
+ }, getIteratee);
/**
* Invokes the method at `path` of `object`.
/**
* The opposite of `_.mapValues`; this method creates an object with the
* same values as `object` and keys generated by running each own enumerable
- * property of `object` through `iteratee`.
+ * property of `object` through `iteratee`. The iteratee is invoked with
+ * three arguments: (value, key, object).
*
* @static
* @memberOf _
/**
* Creates an object with the same keys as `object` and values generated by
* running each own enumerable property of `object` through `iteratee`. The
- * iteratee function is invoked with three arguments: (value, key, object).
+ * iteratee is invoked with three arguments: (value, key, object).
*
* @static
* @memberOf _
* _.mapValues(users, function(o) { return o.age; });
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.mapValues(users, 'age');
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
*/
}
/**
- * Recursively merges own and inherited enumerable properties of source
- * objects into the destination object, skipping source properties that resolve
- * to `undefined`. Array and plain object properties are merged recursively.
- * Other objects and value types are overridden by assignment. Source objects
- * are applied from left to right. Subsequent sources overwrite property
- * assignments of previous sources.
+ * Recursively merges own and inherited enumerable properties of source objects
+ * into the destination object. Source properties that resolve to `undefined`
+ * are skipped if a destination value exists. Array and plain object properties
+ * are merged recursively. Other objects and value types are overridden by
+ * assignment. Source objects are applied from left to right. Subsequent
+ * sources overwrite property assignments of previous sources.
*
* **Note:** This method mutates `object`.
*
* _.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);
});
/**
* method instead. The `customizer` is invoked with seven arguments:
* (objValue, srcValue, key, object, source, stack).
*
+ * **Note:** This method mutates `object`.
+ *
* @static
* @memberOf _
* @category Object
* _.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);
});
/**
* @category Object
* @param {Object} object The source object.
* @param {...(string|string[])} [props] The property names to omit, specified
- * individually or in arrays..
+ * individually or in arrays.
* @returns {Object} Returns the new object.
* @example
*
if (object == null) {
return {};
}
- props = arrayMap(baseFlatten(props), String);
+ props = arrayMap(baseFlatten(props, 1), String);
return basePick(object, baseDifference(keysIn(object), props));
});
/**
- * The opposite of `_.pickBy`; this method creates an object composed of the
- * own and inherited enumerable properties of `object` that `predicate`
- * doesn't return truthy for.
+ * The opposite of `_.pickBy`; this method creates an object composed of
+ * the own and inherited enumerable properties of `object` that `predicate`
+ * doesn't return truthy for. The predicate is invoked with two arguments:
+ * (value, key).
*
* @static
* @memberOf _
*/
function omitBy(object, predicate) {
predicate = getIteratee(predicate);
- return basePickBy(object, function(value) {
- return !predicate(value);
+ return basePickBy(object, function(value, key) {
+ return !predicate(value, key);
});
}
* // => { 'a': 1, 'c': 3 }
*/
var pick = rest(function(object, props) {
- return object == null ? {} : basePick(object, baseFlatten(props));
+ return object == null ? {} : basePick(object, baseFlatten(props, 1));
});
/**
* Creates an object composed of the `object` properties `predicate` returns
- * truthy for. The predicate is invoked with one argument: (value).
+ * truthy for. The predicate is invoked with two arguments: (value, key).
*
* @static
* @memberOf _
*/
function result(object, path, defaultValue) {
if (!isKey(path, object)) {
- path = baseToPath(path);
+ path = baseCastPath(path);
var result = get(object, path);
object = parent(object, path);
} else {
* are created for all other missing properties. Use `_.setWith` to customize
* `path` creation.
*
+ * **Note:** This method mutates `object`.
+ *
* @static
* @memberOf _
* @category Object
* path creation is handled by the method instead. The `customizer` is invoked
* with three arguments: (nsValue, key, nsObject).
*
+ * **Note:** This method mutates `object`.
+ *
* @static
* @memberOf _
* @category Object
}
/**
- * Creates an array of own enumerable key-value pairs for `object`.
+ * Creates an array of own enumerable key-value pairs for `object` which
+ * can be consumed by `_.fromPairs`.
*
* @static
* @memberOf _
}
/**
- * Creates an array of own and inherited enumerable key-value pairs for `object`.
+ * Creates an array of own and inherited enumerable key-value pairs for
+ * `object` which can be consumed by `_.fromPairs`.
*
* @static
* @memberOf _
* _.transform([2, 3, 4], function(result, n) {
* result.push(n *= n);
* return n % 2 == 0;
- * });
+ * }, []);
* // => [4, 9]
*
* _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
* (result[value] || (result[value] = [])).push(key);
- * });
+ * }, {});
* // => { '1': ['a', 'c'], '2': ['b'] }
*/
function transform(object, iteratee, accumulator) {
if (isArr) {
accumulator = isArray(object) ? new Ctor : [];
} else {
- accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined);
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototypeOf(object)) : {};
}
} else {
accumulator = {};
/**
* Removes the property at `path` of `object`.
*
+ * **Note:** This method mutates `object`.
+ *
* @static
* @memberOf _
* @category Object
* // => [1, 2, 3] (iteration order is not guaranteed)
*/
function valuesIn(object) {
- return object == null ? baseValues(object, keysIn(object)) : [];
+ return object == null ? [] : baseValues(object, keysIn(object));
}
/*------------------------------------------------------------------------*/
* `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
* @memberOf _
* @category String
* @param {string} string The string to convert.
- * @param {number} [radix] The radix to interpret `value` by.
+ * @param {number} [radix=10] The radix to interpret `value` by.
* @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
* @returns {number} Returns the converted integer.
* @example
* in "interpolate" delimiters, HTML-escape interpolated data properties in
* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
* properties may be accessed as free variables in the template. If a setting
- * object is provided it takes precedence over `_.templateSettings` values.
+ * object is given it takes precedence over `_.templateSettings` values.
*
* **Note:** In the development build `_.template` utilizes
* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* @returns {Function} Returns the compiled template function.
* @example
*
- * // using the "interpolate" delimiter to create a compiled template
+ * // Use the "interpolate" delimiter to create a compiled template.
* var compiled = _.template('hello <%= user %>!');
* compiled({ 'user': 'fred' });
* // => 'hello fred!'
*
- * // using the HTML "escape" delimiter to escape data property values
+ * // Use the HTML "escape" delimiter to escape data property values.
* var compiled = _.template('<b><%- value %></b>');
* compiled({ 'value': '<script>' });
* // => '<b><script></b>'
*
- * // using the "evaluate" delimiter to execute JavaScript and generate HTML
+ * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
* compiled({ 'users': ['fred', 'barney'] });
* // => '<li>fred</li><li>barney</li>'
*
- * // using the internal `print` function in "evaluate" delimiters
+ * // Use the internal `print` function in "evaluate" delimiters.
* var compiled = _.template('<% print("hello " + user); %>!');
* compiled({ 'user': 'barney' });
* // => 'hello barney!'
*
- * // using the ES delimiter as an alternative to the default "interpolate" delimiter
+ * // Use the ES delimiter as an alternative to the default "interpolate" delimiter.
* var compiled = _.template('hello ${ user }!');
* compiled({ 'user': 'pebbles' });
* // => 'hello pebbles!'
*
- * // using custom template delimiters
+ * // Use custom template delimiters.
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
* var compiled = _.template('hello {{ user }}!');
* compiled({ 'user': 'mustache' });
* // => 'hello mustache!'
*
- * // using backslashes to treat delimiters as plain text
+ * // Use backslashes to treat delimiters as plain text.
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
* compiled({ 'value': 'ignored' });
* // => '<%- value %>'
*
- * // using the `imports` option to import `jQuery` as `jq`
+ * // Use the `imports` option to import `jQuery` as `jq`.
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
* compiled({ 'users': ['fred', 'barney'] });
* // => '<li>fred</li><li>barney</li>'
*
- * // using the `sourceURL` option to specify a custom sourceURL for the template
+ * // Use the `sourceURL` option to specify a custom sourceURL for the template.
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
* compiled(data);
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
*
- * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+ * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
* compiled.source;
* // => function(data) {
* // return __p;
* // }
*
- * // using the `source` property to inline compiled templates for meaningful
- * // line numbers in error messages and a stack trace
+ * // Use the `source` property to inline compiled templates for meaningful
+ * // line numbers in error messages and stack traces.
* fs.writeFileSync(path.join(cwd, 'jst.js'), '\
* var JST = {\
* "main": ' + _.template(mainText).source + '\
'return __p\n}';
var result = attempt(function() {
- return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);
+ return Function(importsKeys, sourceURL + 'return ' + source)
+ .apply(undefined, importsValues);
});
// Provide the compiled function's source by its `toString` method or
var strSymbols = stringToArray(string),
chrSymbols = stringToArray(chars);
- return strSymbols.slice(charsStartIndex(strSymbols, chrSymbols), charsEndIndex(strSymbols, chrSymbols) + 1).join('');
+ return strSymbols
+ .slice(charsStartIndex(strSymbols, chrSymbols), charsEndIndex(strSymbols, chrSymbols) + 1)
+ .join('');
}
/**
return string;
}
var strSymbols = stringToArray(string);
- return strSymbols.slice(0, charsEndIndex(strSymbols, stringToArray(chars)) + 1).join('');
+ return strSymbols
+ .slice(0, charsEndIndex(strSymbols, stringToArray(chars)) + 1)
+ .join('');
}
/**
return string;
}
var strSymbols = stringToArray(string);
- return strSymbols.slice(charsStartIndex(strSymbols, stringToArray(chars))).join('');
+ return strSymbols
+ .slice(charsStartIndex(strSymbols, stringToArray(chars)))
+ .join('');
}
/**
* @memberOf _
* @category String
* @param {string} [string=''] The string to truncate.
- * @param {Object} [options] The options object.
+ * @param {Object} [options=({})] The options object.
* @param {number} [options.length=30] The maximum string length.
* @param {string} [options.omission='...'] The string to indicate text is omitted.
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
* @returns {*} Returns the `func` result or error object.
* @example
*
- * // avoid throwing errors for invalid selectors
+ * // Avoid throwing errors for invalid selectors.
* var elements = _.attempt(function(selector) {
* return document.querySelectorAll(selector);
* }, '>_>');
* // => logs 'clicked docs' when clicked
*/
var bindAll = rest(function(object, methodNames) {
- arrayEach(baseFlatten(methodNames), function(key) {
+ arrayEach(baseFlatten(methodNames, 1), function(key) {
object[key] = bind(object[key], object);
});
return object;
* [_.matches({ 'a': 1 }), _.constant('matches A')],
* [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
* [_.constant(true), _.constant('no match')]
- * ])
+ * ]);
*
* func({ 'a': 1, 'b': 2 });
* // => 'matches A'
}
/**
- * Creates a function that returns the result of invoking the provided
- * functions with the `this` binding of the created function, where each
- * successive invocation is supplied the return value of the previous.
+ * Creates a function that returns the result of invoking the given functions
+ * with the `this` binding of the created function, where each successive
+ * invocation is supplied the return value of the previous.
*
* @static
* @memberOf _
/**
* This method is like `_.flow` except that it creates a function that
- * invokes the provided functions from right to left.
+ * invokes the given functions from right to left.
*
* @static
* @memberOf _
var flowRight = createFlow(true);
/**
- * This method returns the first argument provided to it.
+ * This method returns the first argument given to it.
*
* @static
* @memberOf _
* 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`.
+ * callback returns `true` for elements that contain the equivalent object
+ * properties, otherwise it returns `false`.
*
* @static
* @memberOf _
* { 'user': 'fred', 'age': 40 }
* ];
*
- * // create custom iteratee shorthands
+ * // Create custom iteratee shorthands.
* _.iteratee = _.wrap(_.iteratee, function(callback, func) {
* var p = /^(\S+)\s*([<>])\s*(\S+)$/.exec(func);
* return !p ? callback(func) : function(object) {
* // => [{ 'user': 'fred', 'age': 40 }]
*/
function iteratee(func) {
- return (isObjectLike(func) && !isArray(func))
- ? matches(func)
- : baseIteratee(func);
+ return baseIteratee(typeof func == 'function' ? func : baseClone(func, true));
}
/**
- * Creates a function that performs a deep partial comparison between a given
+ * Creates a function that performs a partial deep comparison between a given
* object and `source`, returning `true` if the given object has equivalent
- * property values, else `false`.
+ * property values, else `false`. The created function is equivalent to
+ * `_.isMatch` with a `source` partially applied.
*
* **Note:** This method supports comparing the same values as `_.isEqual`.
*
}
/**
- * Creates a function that performs a deep partial comparison between the
+ * Creates a function that performs a partial deep comparison between the
* value at `path` of a given object to `srcValue`, returning `true` if the
* object value is equivalent, else `false`.
*
* var lodash = _.noConflict();
*/
function noConflict() {
- root._ = oldDash;
+ if (root._ === this) {
+ root._ = oldDash;
+ }
return this;
}
* 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.
var rangeRight = createRange(true);
/**
- * Invokes the iteratee function `n` times, returning an array of the results
- * of each invocation. The iteratee is invoked with one argument; (index).
+ * Invokes the iteratee `n` times, returning an array of the results of
+ * each invocation. The iteratee is invoked with one argument; (index).
*
* @static
* @memberOf _
var index = MAX_ARRAY_LENGTH,
length = nativeMin(n, MAX_ARRAY_LENGTH);
- iteratee = toFunction(iteratee);
+ iteratee = baseCastFunction(iteratee);
n -= MAX_ARRAY_LENGTH;
var result = baseTimes(length, iteratee);
}
/**
- * Generates a unique ID. If `prefix` is provided the ID is appended to it.
+ * Generates a unique ID. If `prefix` is given the ID is appended to it.
*
* @static
* @memberOf _
* @category Util
- * @param {string} [prefix] The value to prefix the ID with.
+ * @param {string} [prefix=''] The value to prefix the ID with.
* @returns {string} Returns the unique ID.
* @example
*
*/
function add(augend, addend) {
var result;
+ if (augend === undefined && addend === undefined) {
+ return 0;
+ }
if (augend !== undefined) {
result = augend;
}
*
* 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
+ * // The `_.property` iteratee shorthand.
* _.maxBy(objects, 'n');
* // => { 'n': 2 }
*/
*
* 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
+ * // The `_.property` iteratee shorthand.
* _.minBy(objects, 'n');
* // => { 'n': 1 }
*/
*/
function subtract(minuend, subtrahend) {
var result;
+ if (minuend === undefined && subtrahend === undefined) {
+ return 0;
+ }
if (minuend !== undefined) {
result = minuend;
}
function sum(array) {
return (array && array.length)
? baseSum(array, identity)
- : undefined;
+ : 0;
}
/**
* _.sumBy(objects, function(o) { return o.n; });
* // => 20
*
- * // using the `_.property` iteratee shorthand
+ * // The `_.property` iteratee shorthand.
* _.sumBy(objects, 'n');
* // => 20
*/
function sumBy(array, iteratee) {
return (array && array.length)
? baseSum(array, getIteratee(iteratee))
- : undefined;
+ : 0;
}
/*------------------------------------------------------------------------*/
lodash.bind = bind;
lodash.bindAll = bindAll;
lodash.bindKey = bindKey;
+ lodash.castArray = castArray;
lodash.chain = chain;
lodash.chunk = chunk;
lodash.compact = compact;
lodash.flatMap = flatMap;
lodash.flatten = flatten;
lodash.flattenDeep = flattenDeep;
+ lodash.flattenDepth = flattenDepth;
lodash.flip = flip;
lodash.flow = flow;
lodash.flowRight = flowRight;
lodash.intersectionBy = intersectionBy;
lodash.intersectionWith = intersectionWith;
lodash.invert = invert;
+ lodash.invertBy = invertBy;
lodash.invokeMap = invokeMap;
lodash.iteratee = iteratee;
lodash.keyBy = keyBy;
lodash.xorWith = xorWith;
lodash.zip = zip;
lodash.zipObject = zipObject;
+ lodash.zipObjectDeep = zipObjectDeep;
lodash.zipWith = zipWith;
// Add aliases.
- lodash.each = forEach;
- lodash.eachRight = forEachRight;
lodash.extend = assignIn;
lodash.extendWith = assignInWith;
lodash.invoke = invoke;
lodash.isArguments = isArguments;
lodash.isArray = isArray;
+ lodash.isArrayBuffer = isArrayBuffer;
lodash.isArrayLike = isArrayLike;
lodash.isArrayLikeObject = isArrayLikeObject;
lodash.isBoolean = isBoolean;
+ lodash.isBuffer = isBuffer;
lodash.isDate = isDate;
lodash.isElement = isElement;
lodash.isEmpty = isEmpty;
lodash.isFunction = isFunction;
lodash.isInteger = isInteger;
lodash.isLength = isLength;
+ lodash.isMap = isMap;
lodash.isMatch = isMatch;
lodash.isMatchWith = isMatchWith;
lodash.isNaN = isNaN;
lodash.isPlainObject = isPlainObject;
lodash.isRegExp = isRegExp;
lodash.isSafeInteger = isSafeInteger;
+ lodash.isSet = isSet;
lodash.isString = isString;
lodash.isSymbol = isSymbol;
lodash.isTypedArray = isTypedArray;
lodash.isUndefined = isUndefined;
+ lodash.isWeakMap = isWeakMap;
+ lodash.isWeakSet = isWeakSet;
lodash.join = join;
lodash.kebabCase = kebabCase;
lodash.last = last;
lodash.upperFirst = upperFirst;
// Add aliases.
+ lodash.each = forEach;
+ lodash.eachRight = forEachRight;
lodash.first = head;
mixin(lodash, (function() {
*
* @static
* @memberOf _
- * @type string
+ * @type {string}
*/
lodash.VERSION = VERSION;
if (filtered) {
result.__takeCount__ = nativeMin(n, result.__takeCount__);
} else {
- result.__views__.push({ 'size': nativeMin(n, MAX_ARRAY_LENGTH), 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') });
+ result.__views__.push({
+ 'size': nativeMin(n, MAX_ARRAY_LENGTH),
+ 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
+ });
}
return result;
};
LazyWrapper.prototype[methodName] = function(iteratee) {
var result = this.clone();
- result.__iteratees__.push({ 'iteratee': getIteratee(iteratee, 3), 'type': type });
+ result.__iteratees__.push({
+ 'iteratee': getIteratee(iteratee, 3),
+ 'type': type
+ });
result.__filtered__ = result.__filtered__ || isFilter;
return result;
};
}
});
- realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }];
+ realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{
+ 'name': 'wrapper',
+ 'func': undefined
+ }];
// Add functions to the lazy wrapper.
LazyWrapper.prototype.clone = lazyClone;