/** * lodash 4.4.0 (Custom Build) * Build: `lodash modularize exports="npm" -o ./` * Copyright 2012-2016 The Dojo Foundation * Based on Underscore.js 1.8.3 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ var Stack = require('lodash._stack'), baseSlice = require('lodash._baseslice'), root = require('lodash._root'), toString = require('lodash.tostring'); /** Used to compose bitmasks for comparison styles. */ var UNORDERED_COMPARE_FLAG = 1, PARTIAL_COMPARE_FLAG = 2; /** Used as references for various `Number` constants. */ var MAX_SAFE_INTEGER = 9007199254740991; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', boolTag = '[object Boolean]', dateTag = '[object Date]', errorTag = '[object Error]', funcTag = '[object Function]', genTag = '[object GeneratorFunction]', mapTag = '[object Map]', numberTag = '[object Number]', objectTag = '[object Object]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', symbolTag = '[object Symbol]', weakMapTag = '[object WeakMap]'; var arrayBufferTag = '[object ArrayBuffer]', float32Tag = '[object Float32Array]', float64Tag = '[object Float64Array]', int8Tag = '[object Int8Array]', int16Tag = '[object Int16Array]', int32Tag = '[object Int32Array]', uint8Tag = '[object Uint8Array]', uint8ClampedTag = '[object Uint8ClampedArray]', uint16Tag = '[object Uint16Array]', uint32Tag = '[object Uint32Array]'; /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g; /** Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; /** Used to detect host constructors (Safari > 5). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|[1-9]\d*)$/; /** Used to identify `toStringTag` values of typed arrays. */ var typedArrayTags = {}; typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; /** * A specialized version of `_.map` for arrays without support for iteratee * shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { result[index] = iteratee(array[index], index, array); } return result; } /** * A specialized version of `_.some` for arrays without support for iteratee * shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`. */ function arraySome(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (predicate(array[index], index, array)) { return true; } } return false; } /** * The base implementation of `_.times` without support for iteratee shorthands * or max array length checks. * * @private * @param {number} n The number of times to invoke `iteratee`. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the array of results. */ function baseTimes(n, iteratee) { var index = -1, result = Array(n); while (++index < n) { result[index] = iteratee(index); } return result; } /** * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array * of key-value pairs for `object` corresponding to the property names of `props`. * * @private * @param {Object} object The object to query. * @param {Array} props The property names to get values for. * @returns {Object} Returns the new array of key-value pairs. */ function baseToPairs(object, props) { return arrayMap(props, function(key) { return [key, object[key]]; }); } /** * Checks if `value` is a host object in IE < 9. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ function isHostObject(value) { // Many host objects are `Object` objects that can coerce to strings // despite having improperly defined `toString` methods. var result = false; if (value != null && typeof value.toString != 'function') { try { result = !!(value + ''); } catch (e) {} } return result; } /** * Checks if `value` is a valid array-like index. * * @private * @param {*} value The value to check. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; length = length == null ? MAX_SAFE_INTEGER : length; return value > -1 && value % 1 == 0 && value < length; } /** * Converts `map` to an array. * * @private * @param {Object} map The map to convert. * @returns {Array} Returns the converted array. */ function mapToArray(map) { var index = -1, result = Array(map.size); map.forEach(function(value, key) { result[++index] = [key, value]; }); return result; } /** * Converts `set` to an array. * * @private * @param {Object} set The set to convert. * @returns {Array} Returns the converted array. */ function setToArray(set) { var index = -1, result = Array(set.size); set.forEach(function(value) { result[++index] = value; }); return result; } /** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to resolve the decompiled source of functions. */ var funcToString = Function.prototype.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Built-in value references. */ var Symbol = root.Symbol, Uint8Array = root.Uint8Array, getPrototypeOf = Object.getPrototypeOf, propertyIsEnumerable = objectProto.propertyIsEnumerable; /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeKeys = Object.keys; /* Built-in method references that are verified to be native. */ var Map = getNative(root, 'Map'), Set = getNative(root, 'Set'), WeakMap = getNative(root, 'WeakMap'); /** Used to detect maps, sets, and weakmaps. */ var mapCtorString = Map ? funcToString.call(Map) : '', 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; /** * 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 `_.get` without support for default values. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @returns {*} Returns the resolved value. */ function baseGet(object, path) { path = isKey(path, object) ? [path + ''] : baseCastPath(path); var index = 0, length = path.length; while (object != null && index < length) { object = object[path[index++]]; } return (index && index == length) ? object : undefined; } /** * The base implementation of `_.has` without support for deep paths. * * @private * @param {Object} object The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHas(object, key) { // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`, // that are composed entirely of index properties, return `false` for // `hasOwnProperty` checks of them. return hasOwnProperty.call(object, key) || (typeof object == 'object' && key in object && getPrototypeOf(object) === null); } /** * The base implementation of `_.hasIn` without support for deep paths. * * @private * @param {Object} object The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHasIn(object, key) { return key in Object(object); } /** * The base implementation of `_.isEqual` which supports partial comparisons * and tracks traversed objects. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparisons. * @param {boolean} [bitmask] The bitmask of comparison flags. * The bitmask may be composed of the following flags: * 1 - Unordered comparison * 2 - Partial comparison * @param {Object} [stack] Tracks traversed `value` and `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, bitmask, stack) { if (value === other) { return true; } if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { return value !== value && other !== other; } return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack); } /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular * references to be compared. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparisons. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; if (!objIsArr) { objTag = getTag(object); if (objTag == argsTag) { objTag = objectTag; } else if (objTag != objectTag) { objIsArr = isTypedArray(object); } } if (!othIsArr) { othTag = getTag(other); if (othTag == argsTag) { othTag = objectTag; } else if (othTag != objectTag) { othIsArr = isTypedArray(other); } } var objIsObj = objTag == objectTag && !isHostObject(object), othIsObj = othTag == objectTag && !isHostObject(other), isSameTag = objTag == othTag; if (isSameTag && !(objIsArr || objIsObj)) { return equalByTag(object, other, objTag, equalFunc, customizer, bitmask); } var isPartial = bitmask & PARTIAL_COMPARE_FLAG; if (!isPartial) { var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (objIsWrapped || othIsWrapped) { return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, bitmask, stack); } } if (!isSameTag) { return false; } stack || (stack = new Stack); return (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack); } /** * The base implementation of `_.isMatch` without support for iteratee shorthands. * * @private * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Array} matchData The property names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, source, matchData, customizer) { var index = matchData.length, length = index, noCustomizer = !customizer; if (object == null) { return !length; } object = Object(object); while (index--) { var data = matchData[index]; if ((noCustomizer && data[2]) ? data[1] !== object[data[0]] : !(data[0] in object) ) { return false; } } while (++index < length) { data = matchData[index]; var key = data[0], objValue = object[key], srcValue = data[1]; if (noCustomizer && data[2]) { if (objValue === undefined && !(key in object)) { return false; } } else { var stack = new Stack, result = customizer ? customizer(objValue, srcValue, key, object, source, stack) : undefined; if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) : result )) { return false; } } } return true; } /** * The base implementation of `_.iteratee`. * * @private * @param {*} [value=_.identity] The value to convert to an iteratee. * @returns {Function} Returns the iteratee. */ function baseIteratee(value) { var type = typeof value; if (type == 'function') { return value; } if (value == null) { return identity; } if (type == 'object') { return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value); } return property(value); } /** * The base implementation of `_.keys` which doesn't skip the constructor * property of prototypes or treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeys(object) { return nativeKeys(Object(object)); } /** * The base implementation of `_.matches` which doesn't clone `source`. * * @private * @param {Object} source The object of property values to match. * @returns {Function} Returns the new function. */ function baseMatches(source) { var matchData = getMatchData(source); if (matchData.length == 1 && matchData[0][2]) { var key = matchData[0][0], value = matchData[0][1]; return function(object) { if (object == null) { return false; } return object[key] === value && (value !== undefined || (key in Object(object))); }; } return function(object) { return object === source || baseIsMatch(object, source, matchData); }; } /** * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. * * @private * @param {string} path The path of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new function. */ function baseMatchesProperty(path, srcValue) { return function(object) { var objValue = get(object, path); return (objValue === undefined && objValue === srcValue) ? hasIn(object, path) : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG); }; } /** * The base implementation of `_.property` without support for deep paths. * * @private * @param {string} key The key of the property to get. * @returns {Function} Returns the new function. */ function baseProperty(key) { return function(object) { return object == null ? undefined : object[key]; }; } /** * A specialized version of `baseProperty` which supports deep paths. * * @private * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new function. */ function basePropertyDeep(path) { return function(object) { return baseGet(object, path); }; } /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. * * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparisons. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. * @param {Object} [stack] Tracks traversed `array` and `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { var index = -1, isPartial = bitmask & PARTIAL_COMPARE_FLAG, isUnordered = bitmask & UNORDERED_COMPARE_FLAG, arrLength = array.length, othLength = other.length; if (arrLength != othLength && !(isPartial && othLength > arrLength)) { return false; } // Assume cyclic values are equal. var stacked = stack.get(array); if (stacked) { return stacked == other; } var result = true; stack.set(array, other); // Ignore non-index properties. while (++index < arrLength) { var arrValue = array[index], othValue = other[index]; if (customizer) { var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack); } if (compared !== undefined) { if (compared) { continue; } result = false; break; } // Recursively compare arrays (susceptible to call stack limits). if (isUnordered) { if (!arraySome(other, function(othValue) { return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack); })) { result = false; break; } } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { result = false; break; } } stack['delete'](array); return result; } /** * A specialized version of `baseIsEqualDeep` for comparing objects of * the same `toStringTag`. * * **Note:** This function only supports comparing values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparisons. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalByTag(object, other, tag, equalFunc, customizer, bitmask) { switch (tag) { case arrayBufferTag: if ((object.byteLength != other.byteLength) || !equalFunc(new Uint8Array(object), new Uint8Array(other))) { return false; } return true; case boolTag: case dateTag: // Coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. return +object == +other; case errorTag: return object.name == other.name && object.message == other.message; case numberTag: // Treat `NaN` vs. `NaN` as equal. return (object != +object) ? other != +other : object == +other; case regexpTag: case stringTag: // Coerce regexes to strings and treat strings primitives and string // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. return object == (other + ''); case mapTag: var convert = mapToArray; case setTag: var isPartial = bitmask & PARTIAL_COMPARE_FLAG; convert || (convert = setToArray); // Recursively compare objects (susceptible to call stack limits). return (isPartial || object.size == other.size) && equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG); case symbolTag: return !!Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other)); } return false; } /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparisons. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details. * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { var isPartial = bitmask & PARTIAL_COMPARE_FLAG, objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; if (objLength != othLength && !isPartial) { return false; } var index = objLength; while (index--) { var key = objProps[index]; if (!(isPartial ? key in other : baseHas(other, key))) { return false; } } // Assume cyclic values are equal. var stacked = stack.get(object); if (stacked) { return stacked == other; } var result = true; stack.set(object, other); var skipCtor = isPartial; while (++index < objLength) { key = objProps[index]; var objValue = object[key], othValue = other[key]; if (customizer) { var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack); } // Recursively compare objects (susceptible to call stack limits). if (!(compared === undefined ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) : compared )) { result = false; break; } skipCtor || (skipCtor = key == 'constructor'); } if (result && !skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal. if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { result = false; } } stack['delete'](object); return result; } /** * Gets the "length" property value of `object`. * * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) * that affects Safari on at least iOS 8.1-8.3 ARM64. * * @private * @param {Object} object The object to query. * @returns {*} Returns the "length" value. */ var getLength = baseProperty('length'); /** * Gets the property names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { var result = toPairs(object), length = result.length; while (length--) { result[length][2] = isStrictComparable(result[length][1]); } return result; } /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { var value = object == null ? undefined : object[key]; return isNative(value) ? value : undefined; } /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function getTag(value) { return objectToString.call(value); } // Fallback for IE 11 providing `toStringTag` values for maps, 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) { switch (ctorString) { case mapCtorString: return mapTag; case setCtorString: return setTag; case weakMapCtorString: return weakMapTag; } } return result; }; } /** * Checks if `path` exists on `object`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @param {Function} hasFunc The function to check properties. * @returns {boolean} Returns `true` if `path` exists, else `false`. */ function hasPath(object, path, hasFunc) { if (object == null) { return false; } var result = hasFunc(object, path); if (!result && !isKey(path)) { path = baseCastPath(path); object = parent(object, path); if (object != null) { path = last(path); result = hasFunc(object, path); } } var length = object ? object.length : undefined; return result || ( !!length && isLength(length) && isIndex(path, length) && (isArray(object) || isString(object) || isArguments(object)) ); } /** * Creates an array of index keys for `object` values of arrays, * `arguments` objects, and strings, otherwise `null` is returned. * * @private * @param {Object} object The object to query. * @returns {Array|null} Returns index keys, else `null`. */ function indexKeys(object) { var length = object ? object.length : undefined; if (isLength(length) && (isArray(object) || isString(object) || isArguments(object))) { return baseTimes(length, String); } return null; } /** * Checks if `value` is a property name and not a property path. * * @private * @param {*} value The value to check. * @param {Object} [object] The object to query keys on. * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { if (typeof value == 'number') { return true; } return !isArray(value) && (reIsPlainProp.test(value) || !reIsDeepProp.test(value) || (object != null && value in Object(object))); } /** * Checks if `value` is likely a prototype object. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. */ function isPrototype(value) { var Ctor = value && value.constructor, proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; return value === proto; } /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` if suitable for strict * equality comparisons, else `false`. */ function isStrictComparable(value) { return value === value && !isObject(value); } /** * Gets the parent value at `path` of `object`. * * @private * @param {Object} object The object to query. * @param {Array} path The path to get the parent value of. * @returns {*} Returns the parent value. */ function parent(object, path) { return path.length == 1 ? object : get(object, baseSlice(path, 0, -1)); } /** * Converts `string` to a property path array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ function stringToPath(string) { var result = []; toString(string).replace(rePropName, function(match, number, quote, string) { result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); }); return result; } /** * Gets the last element of `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to query. * @returns {*} Returns the last element of `array`. * @example * * _.last([1, 2, 3]); * // => 3 */ function last(array) { var length = array ? array.length : 0; return length ? array[length - 1] : undefined; } /** * Checks if `value` is likely an `arguments` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isArguments(function() { return arguments; }()); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @type {Function} * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * _.isArray(document.body.children); * // => false * * _.isArray('abc'); * // => false * * _.isArray(_.noop); * // => false */ var isArray = Array.isArray; /** * Checks if `value` is array-like. A value is considered array-like if it's * not a function and has a `value.length` that's an integer greater than or * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. * @example * * _.isArrayLike([1, 2, 3]); * // => true * * _.isArrayLike(document.body.children); * // => true * * _.isArrayLike('abc'); * // => true * * _.isArrayLike(_.noop); * // => false */ function isArrayLike(value) { return value != null && !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value)); } /** * This method is like `_.isArrayLike` except that it also checks if `value` * is an object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. * @example * * _.isArrayLikeObject([1, 2, 3]); * // => true * * _.isArrayLikeObject(document.body.children); * // => true * * _.isArrayLikeObject('abc'); * // => false * * _.isArrayLikeObject(_.noop); * // => false */ function isArrayLikeObject(value) { return isObjectLike(value) && isArrayLike(value); } /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in Safari 8 which returns 'object' for typed array constructors, and // PhantomJS 1.9 which returns 'function' for `NodeList` instances. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } /** * Checks if `value` is a valid array-like length. * * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. * @example * * _.isLength(3); * // => true * * _.isLength(Number.MIN_VALUE); * // => false * * _.isLength(Infinity); * // => false * * _.isLength('3'); * // => false */ function isLength(value) { return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } /** * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(_.noop); * // => true * * _.isObject(null); * // => false */ function isObject(value) { var type = typeof value; return !!value && (type == 'object' || type == 'function'); } /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. * @example * * _.isObjectLike({}); * // => true * * _.isObjectLike([1, 2, 3]); * // => true * * _.isObjectLike(_.noop); * // => false * * _.isObjectLike(null); * // => false */ function isObjectLike(value) { return !!value && typeof value == 'object'; } /** * Checks if `value` is a native function. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, else `false`. * @example * * _.isNative(Array.prototype.push); * // => true * * _.isNative(_); * // => false */ function isNative(value) { if (value == null) { return false; } if (isFunction(value)) { return reIsNative.test(funcToString.call(value)); } return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value); } /** * Checks if `value` is classified as a `String` primitive or object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isString('abc'); * // => true * * _.isString(1); * // => false */ function isString(value) { return typeof value == 'string' || (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); } /** * Checks if `value` is classified as a typed array. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isTypedArray(new Uint8Array); * // => true * * _.isTypedArray([]); * // => false */ function isTypedArray(value) { return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; } /** * Gets the value at `path` of `object`. If the resolved value is * `undefined` the `defaultValue` is used in its place. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @param {*} [defaultValue] The value returned if the resolved value is `undefined`. * @returns {*} Returns the resolved value. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * * _.get(object, 'a[0].b.c'); * // => 3 * * _.get(object, ['a', '0', 'b', 'c']); * // => 3 * * _.get(object, 'a.b.c', 'default'); * // => 'default' */ function get(object, path, defaultValue) { var result = object == null ? undefined : baseGet(object, path); return result === undefined ? defaultValue : result; } /** * Checks if `path` is a direct or inherited property of `object`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * * var object = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) }); * * _.hasIn(object, 'a'); * // => true * * _.hasIn(object, 'a.b.c'); * // => true * * _.hasIn(object, ['a', 'b', 'c']); * // => true * * _.hasIn(object, 'b'); * // => false */ function hasIn(object, path) { return hasPath(object, path, baseHasIn); } /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) * for more details. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keys(new Foo); * // => ['a', 'b'] (iteration order is not guaranteed) * * _.keys('hi'); * // => ['0', '1'] */ function keys(object) { var isProto = isPrototype(object); if (!(isProto || isArrayLike(object))) { return baseKeys(object); } var indexes = indexKeys(object), skipIndexes = !!indexes, result = indexes || [], length = result.length; for (var key in object) { if (baseHas(object, key) && !(skipIndexes && (key == 'length' || isIndex(key, length))) && !(isProto && key == 'constructor')) { result.push(key); } } return result; } /** * Creates an array of own enumerable key-value pairs for `object` which * can be consumed by `_.fromPairs`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the new array of key-value pairs. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.toPairs(new Foo); * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) */ function toPairs(object) { return baseToPairs(object, keys(object)); } /** * This method returns the first argument given to it. * * @static * @memberOf _ * @category Util * @param {*} value Any value. * @returns {*} Returns `value`. * @example * * var object = { 'user': 'fred' }; * * _.identity(object) === object; * // => true */ function identity(value) { return value; } /** * Creates a function that returns the value at `path` of a given object. * * @static * @memberOf _ * @category Util * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new function. * @example * * var objects = [ * { 'a': { 'b': { 'c': 2 } } }, * { 'a': { 'b': { 'c': 1 } } } * ]; * * _.map(objects, _.property('a.b.c')); * // => [2, 1] * * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); * // => [1, 2] */ function property(path) { return isKey(path) ? baseProperty(path) : basePropertyDeep(path); } module.exports = baseIteratee;