/** * @license * Lo-Dash 3.0.0-pre * Copyright 2012-2014 The Dojo Foundation * Based on Underscore.js 1.7.0 * Copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ ;(function() { /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; /** Used as the semantic version number */ var VERSION = '3.0.0-pre'; /** Used to compose bitmasks for wrapper metadata */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_FLAG = 4, CURRY_RIGHT_FLAG = 8, CURRY_BOUND_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64; /** Used to detect when a function becomes hot */ var HOT_COUNT = 150, HOT_SPAN = 16; /** Used as the TypeError message for "Functions" methods */ var FUNC_ERROR_TEXT = 'Expected a function'; /** Used as references for the max length and index of an array */ var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; /** * Used as the maximum length of an array-like value. * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) * for more details. */ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; /** Used as the internal argument placeholder */ var PLACEHOLDER = '__lodash_placeholder__'; /** Used to generate unique IDs */ var idCounter = 0; /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities and HTML characters */ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g; /** Used to match template delimiters */ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; /** * Used to match ES6 template delimiters. * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) * for more details. */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values */ var reFlags = /\w*$/; /** Used to detect named functions */ var reFuncName = /^\s*function[ \n\r\t]+\w/; /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; /** Used to detect host constructors (Safari > 5) */ var reHostCtor = /^\[object .+?Constructor\]$/; /** Used to match latin-1 supplement letters */ var reLatin1 = /[\xC0-\xFF]/g; /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; /** * Used to match `RegExp` special characters. * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) * for more details. */ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g; /** Used to detect functions containing a `this` reference */ var reThis = /\bthis\b/; /** Used to match unescaped characters in compiled string literals */ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; /** Used to match words to create compound words */ var reWords = (function() { var nums = '[0-9]', upper = '[A-Z\\xC0-\\xD6\\xD8-\\xDE]', lower = '[a-z\\xDF-\\xF6\\xF8-\\xFF]+' + nums + '*'; return RegExp(upper + '{2,}(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|' + nums + '+', 'g'); }()); /** Used to detect and test whitespace */ var whitespace = ( // whitespace ' \t\x0B\f\xA0\ufeff' + // line terminators '\n\r\u2028\u2029' + // unicode category "Zs" space separators '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to assign default `context` object properties */ var contextProps = [ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'window', 'WinRTError' ]; /** Used to fix the JScript `[[DontEnum]]` bug */ var shadowedProps = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; /** Used to make template sourceURLs easier to identify */ var templateCounter = -1; /** `Object#toString` result references */ var argsClass = '[object Arguments]', arrayClass = '[object Array]', boolClass = '[object Boolean]', dateClass = '[object Date]', errorClass = '[object Error]', funcClass = '[object Function]', mapClass = '[object Map]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', setClass = '[object Set]', stringClass = '[object String]', weakMapClass = '[object WeakMap]'; var arrayBufferClass = '[object ArrayBuffer]', float32Class = '[object Float32Array]', float64Class = '[object Float64Array]', int8Class = '[object Int8Array]', int16Class = '[object Int16Array]', int32Class = '[object Int32Array]', uint8Class = '[object Uint8Array]', uint8ClampedClass = '[object Uint8ClampedArray]', uint16Class = '[object Uint16Array]', uint32Class = '[object Uint32Array]'; /** Used to identify object classifications that are treated like arrays */ var arrayLikeClasses = {}; arrayLikeClasses[argsClass] = arrayLikeClasses[arrayClass] = arrayLikeClasses[float32Class] = arrayLikeClasses[float64Class] = arrayLikeClasses[int8Class] = arrayLikeClasses[int16Class] = arrayLikeClasses[int32Class] = arrayLikeClasses[uint8Class] = arrayLikeClasses[uint8ClampedClass] = arrayLikeClasses[uint16Class] = arrayLikeClasses[uint32Class] = true; arrayLikeClasses[arrayBufferClass] = arrayLikeClasses[boolClass] = arrayLikeClasses[dateClass] = arrayLikeClasses[errorClass] = arrayLikeClasses[funcClass] = arrayLikeClasses[mapClass] = arrayLikeClasses[numberClass] = arrayLikeClasses[objectClass] = arrayLikeClasses[regexpClass] = arrayLikeClasses[setClass] = arrayLikeClasses[stringClass] = arrayLikeClasses[weakMapClass] = false; /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; cloneableClasses[argsClass] = cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] = cloneableClasses[float32Class] = cloneableClasses[float64Class] = cloneableClasses[int8Class] = cloneableClasses[int16Class] = cloneableClasses[int32Class] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] = cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true; cloneableClasses[errorClass] = cloneableClasses[funcClass] = cloneableClasses[mapClass] = cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false; /** Used as an internal `_.debounce` options object by `_.throttle` */ var debounceOptions = { 'leading': false, 'maxWait': 0, 'trailing': false }; /** * Used to map characters to HTML entities. * * **Note:** Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias Bynens's article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in Internet Explorer < 9, they can break out * of attribute values or HTML comments. See [#102](http://html5sec.org/#102), * [#108](http://html5sec.org/#108), and [#133](http://html5sec.org/#133) of * the [HTML5 Security Cheatsheet](http://html5sec.org/) for more details. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '`': '`' }; /** Used to map HTML entities to characters */ var htmlUnescapes = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'", '`': '`' }; /** Used to map latin-1 supplementary letters to basic latin letters */ var deburredLetters = { '\xC0': 'A', '\xC1': 'A', '\xC2': 'A', '\xC3': 'A', '\xC4': 'A', '\xC5': 'A', '\xE0': 'a', '\xE1': 'a', '\xE2': 'a', '\xE3': 'a', '\xE4': 'a', '\xE5': 'a', '\xC7': 'C', '\xE7': 'c', '\xD0': 'D', '\xF0': 'd', '\xC8': 'E', '\xC9': 'E', '\xCA': 'E', '\xCB': 'E', '\xE8': 'e', '\xE9': 'e', '\xEA': 'e', '\xEB': 'e', '\xCC': 'I', '\xCD': 'I', '\xCE': 'I', '\xCF': 'I', '\xEC': 'i', '\xED': 'i', '\xEE': 'i', '\xEF': 'i', '\xD1': 'N', '\xF1': 'n', '\xD2': 'O', '\xD3': 'O', '\xD4': 'O', '\xD5': 'O', '\xD6': 'O', '\xD8': 'O', '\xF2': 'o', '\xF3': 'o', '\xF4': 'o', '\xF5': 'o', '\xF6': 'o', '\xF8': 'o', '\xD9': 'U', '\xDA': 'U', '\xDB': 'U', '\xDC': 'U', '\xF9': 'u', '\xFA': 'u', '\xFB': 'u', '\xFC': 'u', '\xDD': 'Y', '\xFD': 'y', '\xFF': 'y', '\xC6': 'Ae', '\xE6': 'ae', '\xDE': 'Th', '\xFE': 'th', '\xDF': 'ss', '\xD7': ' ', '\xF7': ' ' }; /** Used to determine if values are of the language type `Object` */ var objectTypes = { 'function': true, 'object': true }; /** Used to escape characters for inclusion in compiled string literals */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', '\u2028': 'u2028', '\u2029': 'u2029' }; /** Used as a reference to the global object */ var root = (objectTypes[typeof window] && window) || this; /** Detect free variable `exports` */ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; /** Detect free variable `module` */ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { root = freeGlobal; } /** Detect the popular CommonJS extension `module.exports` */ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; /*--------------------------------------------------------------------------*/ /** * A specialized version of `_.forEach` for arrays without support for * callback shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { if (iteratee(array[index], index, array) === false) { break; } } return array; } /** * A specialized version of `_.forEachRight` for arrays without support for * callback shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEachRight(array, iteratee) { var length = array.length; while (length--) { if (iteratee(array[length], length, array) === false) { break; } } return array; } /** * A specialized version of `_.every` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ function arrayEvery(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (!predicate(array[index], index, array)) { return false; } } return true; } /** * A specialized version of `_.map` for arrays without support for callback * shorthands or `this` binding. * * @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 `_.filter` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { var index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result[++resIndex] = value; } } return result; } /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands or `this` binding. * * @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=false] Specify using the first element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; if (initFromArray && length) { accumulator = array[++index]; } while (++index < length) { accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } /** * A specialized version of `_.reduceRight` for arrays without support for * callback shorthands or `this` binding. * * @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=false] Specify using the last element of * `array` as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduceRight(array, iteratee, accumulator, initFromArray) { var length = array.length; if (initFromArray && length) { accumulator = array[--length]; } while (length--) { accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } /** * A specialized version of `_.some` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed 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 `_.at` without support for strings and individual * key arguments. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {number[]|string[]} [props] The property names or indexes of elements to pick. * @returns {Array} Returns the new array of picked elements. */ function baseAt(collection, props) { var index = -1, length = props.length, result = Array(length); while(++index < length) { result[index] = collection[props[index]]; } return result; } /** * The base implementation of `compareAscending` which compares values and * sorts them in ascending order without guaranteeing a stable sort. * * @private * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @returns {number} Returns the sort order indicator for `value`. */ function baseCompareAscending(value, other) { if (value !== other) { var valIsReflexive = value === value, othIsReflexive = other === other; if (value > other || !valIsReflexive || (typeof value == 'undefined' && othIsReflexive)) { return 1; } if (value < other || !othIsReflexive || (typeof other == 'undefined' && valIsReflexive)) { return -1; } } return 0; } /** * The base implementation of `_.indexOf` without support for binary searches. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, isReflexive = value === value; while (++index < length) { var other = array[index]; if ((isReflexive ? other === value : other !== other)) { return index; } } return -1; } /** * The base implementation of `_.slice` without support for `start` and `end` * arguments. * * @private * @param {Array} array The array to slice. * @returns {Array} Returns the slice of `array`. */ function baseSlice(array) { var index = -1, length = array ? array.length : 0, result = Array(length); while (++index < length) { result[index] = array[index]; } return result; } /** * An implementation of `_.contains` for cache objects that mimics the return * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. * * @private * @param {Object} cache The cache object to inspect. * @param {*} value The value to search for. * @returns {number} Returns `0` if `value` is found, else `-1`. */ function cacheIndexOf(cache, value) { return cache.has(value) ? 0 : -1; } /** * Used by `_.max` and `_.min` as the default callback when a given collection * is a string value. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the code unit of the first character of the string. */ function charAtCallback(string) { return string.charCodeAt(0); } /** * Used by `_.trim` and `_.trimLeft` to get the index of the first character * of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. * @param {string} chars The characters to find. * @returns {number} Returns the index of the first character not found in `chars`. */ function charsLeftIndex(string, chars) { var index = -1, length = string.length; while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} return index; } /** * Used by `_.trim` and `_.trimRight` to get the index of the last character * of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. * @param {string} chars The characters to find. * @returns {number} Returns the index of the last character not found in `chars`. */ function charsRightIndex(string, chars) { var index = string.length; while (index-- && chars.indexOf(string.charAt(index)) > -1) {} return index; } /** * Used by `_.sortBy` to compare transformed elements of `collection` and stable * sort them in ascending order. * * @private * @param {Object} object The object to compare to `other`. * @param {Object} other The object to compare to `object`. * @returns {number} Returns the sort order indicator for `object`. */ function compareAscending(object, other) { return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index); } /** * Used by `_.sortBy` to compare multiple properties of each element in a * collection and stable sort them in ascending order. * * @private * @param {Object} object The object to compare to `other`. * @param {Object} other The object to compare to `object`. * @returns {number} Returns the sort order indicator for `object`. */ function compareMultipleAscending(object, other) { var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length; while (++index < length) { var result = baseCompareAscending(objCriteria[index], othCriteria[index]); if (result) { return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications // that causes it, under certain circumstances, to provide the same value // for `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See https://code.google.com/p/v8/issues/detail?id=90 return object.index - other.index; } /** * Used by `deburr` to convert latin-1 to basic latin letters. * * @private * @param {string} letter The matched letter to deburr. * @returns {string} Returns the deburred letter. */ function deburrLetter(letter) { return deburredLetters[letter]; } /** * Used by `_.escape` to convert characters to HTML entities. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeHtmlChar(chr) { return htmlEscapes[chr]; } /** * Used by `_.template` to escape characters for inclusion in compiled * string literals. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeStringChar(chr) { return '\\' + stringEscapes[chr]; } /** * Checks if `value` is a host object in IE < 9. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ var isHostObject = (function() { try { ({ 'toString': 0 } + ''); } catch(e) { return function() { return false; }; } return function(value) { // IE < 9 presents many host objects as `Object` objects that can coerce to // strings despite having improperly defined `toString` methods return typeof value.toString != 'function' && typeof (value + '') == 'string'; }; }()); /** * Used by `_.trimmedLeftIndex` and `_.trimmedRightIndex` to determine if a * character code is whitespace. * * @private * @param {number} charCode The character code to inspect. * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`. */ function isWhitespace(charCode) { return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 || (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279))); } /** * Replaces all `placeholder` elements in `array` with an internal placeholder * and returns an array of their indexes. * * @private * @param {Array} array The array to modify. * @param {*} placeholder The placeholder to replace. * @returns {Array} Returns the new array of placeholder indexes. */ function replaceHolders(array, placeholder) { var index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; result[++resIndex] = index; } } return result; } /** * An implementation of `_.uniq` optimized for sorted arrays without support * for callback shorthands and `this` binding. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function sortedUniq(array, iteratee) { var seen, index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; if (!index || seen !== computed) { seen = computed; result[++resIndex] = value; } } return result; } /** * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace * character of `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the first non-whitespace character. */ function trimmedLeftIndex(string) { var index = -1, length = string.length; while (++index < length && isWhitespace(string.charCodeAt(index))) {} return index; } /** * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace * character of `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the last non-whitespace character. */ function trimmedRightIndex(string) { var index = string.length; while (index-- && isWhitespace(string.charCodeAt(index))) {} return index; } /** * Used by `_.unescape` to convert HTML entities to characters. * * @private * @param {string} chr The matched character to unescape. * @returns {string} Returns the unescaped character. */ function unescapeHtmlChar(chr) { return htmlUnescapes[chr]; } /*--------------------------------------------------------------------------*/ /** * Create a new pristine `lodash` function using the given `context` object. * * @static * @memberOf _ * @category Utility * @param {Object} [context=root] The context object. * @returns {Function} Returns a new `lodash` function. * @example * * _.mixin({ 'add': function(a, b) { return a + b; } }, false); * * var lodash = _.runInContext(); * lodash.mixin({ 'sub': function(a, b) { return a - b; } }, false); * * _.isFunction(_.add); * // => true * * _.isFunction(_.sub); * // => false * * lodash.isFunction(lodash.add); * // => false * * lodash.isFunction(lodash.sub); * // => true */ function runInContext(context) { // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. // See http://es5.github.io/#x11.1.5. context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; /** Native constructor references */ var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; /** Used for native method references */ var arrayProto = Array.prototype, errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype; /** Used to detect DOM support */ var document = (document = context.window) && document.document; /** Used to resolve the decompiled source of functions */ var fnToString = Function.prototype.toString; /** Used to check objects for own properties */ var hasOwnProperty = objectProto.hasOwnProperty; /** Used to restore the original `_` reference in `_.noConflict` */ var oldDash = context._; /** Used to resolve the internal `[[Class]]` of values */ var toString = objectProto.toString; /** Used to detect if a method is native */ var reNative = RegExp('^' + escapeRegExp(toString) .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method references */ var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, unshift = arrayProto.unshift, WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers */ var Float64Array = (function() { // Safari 5 errors when using an array buffer to initialize a typed array // where the array buffer's `byteLength` is not a multiple of the typed // array's `BYTES_PER_ELEMENT` try { var func = isNative(func = context.Float64Array) && func, result = new func(new ArrayBuffer(10), 0, 1) && func; } catch(e) {} return result; }()); /* Native method references for those with the same name as other `lodash` methods */ var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = context.isFinite, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, nativeMax = Math.max, nativeMin = Math.min, nativeNow = isNative(nativeNow = Date.now) && nativeNow, nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite, nativeParseInt = context.parseInt, nativeRandom = Math.random; /** Used as the size, in bytes, of each Float64Array element */ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; /** Used to store function metadata */ var metaMap = WeakMap && new WeakMap; /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; ctorByClass[float32Class] = context.Float32Array; ctorByClass[float64Class] = context.Float64Array; ctorByClass[int8Class] = context.Int8Array; ctorByClass[int16Class] = context.Int16Array; ctorByClass[int32Class] = context.Int32Array; ctorByClass[uint8Class] = context.Uint8Array; ctorByClass[uint8ClampedClass] = context.Uint8ClampedArray; ctorByClass[uint16Class] = context.Uint16Array; ctorByClass[uint32Class] = context.Uint32Array; /** Used to avoid iterating over non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true }; nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true }; nonEnumProps[objectClass] = { 'constructor': true }; arrayEach(shadowedProps, function(key) { for (var className in nonEnumProps) { if (hasOwnProperty.call(nonEnumProps, className)) { var props = nonEnumProps[className]; props[key] = hasOwnProperty.call(props, key); } } }); /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps the given value to enable intuitive * method chaining. * * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * * Chaining is supported in custom builds as long as the `value` method is * implicitly or explicitly included in the build. * * The chainable wrapper functions are: * `after`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, `callback`, * `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, `create`, * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `drop`, * `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, `flattenDeep`, * `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, `forInRight`, * `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, * `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, `mapValues`, * `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, `omit`, `once`, * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `pluck`, `property`, * `pull`, `pullAt`, `push`, `range`, `reject`, `remove`, `rest`, `reverse`, * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `take`, `takeRight`, * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `times`, * `toArray`, `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * * The non-chainable wrapper functions are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `contains`, * `deburr`, endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, * `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, isDate`, * `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, `isFunction`, * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, * `isRegExp`, `isString`, `isUndefined`, `join`, `kebabCase`, `last`, * `lastIndexOf`, `max`, `min`, `noConflict`, `now`, `pad`, `padLeft`, * `padRight`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, * `result`, `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, * `sortedLastIndex`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, * `trunc`, `unescape`, `uniqueId`, `value`, and `words` * * The wrapper function `sample` will return a wrapped value when `n` is * provided, otherwise it will return an unwrapped value. * * Explicit chaining can be enabled by using the `_.chain` method. * * @name _ * @constructor * @category Chain * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns a `lodash` instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash(value) { if (value && typeof value == 'object') { if (value instanceof lodashWrapper) { return value; } if (!isArray(value) && hasOwnProperty.call(value, '__wrapped__')) { return new lodashWrapper(value.__wrapped__, value.__chain__, baseSlice(value.__queue__)); } } return new lodashWrapper(value); } /** * A fast path for creating `lodash` wrapper objects. * * @private * @param {*} value The value to wrap in a `lodash` instance. * @param {boolean} [chainAll=false] Enable chaining for all methods. * @param {Array} [queue=[]] Actions to peform to resolve the unwrapped value. * @returns {Object} Returns a `lodash` instance. */ function lodashWrapper(value, chainAll, queue) { this.__chain__ = !!chainAll; this.__queue__ = queue || []; this.__wrapped__ = value; } /** * An object environment feature flags. * * @static * @memberOf _ * @type Object */ var support = lodash.support = {}; (function(x) { var Ctor = function() { this.x = 1; }, object = { '0': 1, 'length': 1 }, props = []; Ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new Ctor) { props.push(key); } /** * Detect if the `[[Class]]` of `arguments` objects is resolvable * (all but Firefox < 4, IE < 9). * * @memberOf _.support * @type boolean */ support.argsClass = toString.call(arguments) == argsClass; /** * Detect if `name` or `message` properties of `Error.prototype` are * enumerable by default (IE < 9, Safari < 5.1). * * @memberOf _.support * @type boolean */ support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name'); /** * Detect if `prototype` properties are enumerable by default. * * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 * (if the prototype or a property on the prototype has been set) * incorrectly sets the `[[Enumerable]]` value of a function's `prototype` * property to `true`. * * @memberOf _.support * @type boolean */ support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype'); /** * Detect if functions can be decompiled by `Function#toString` * (all but Firefox OS certified apps, older Opera mobile browsers, and * the PlayStation 3; forced `false` for Windows 8 apps). * * @memberOf _.support * @type boolean */ support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); /** * Detect if `Function#name` is supported (all but IE). * * @memberOf _.support * @type boolean */ support.funcNames = typeof Function.name == 'string'; /** * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9). * * @memberOf _.support * @type boolean */ support.nodeClass = toString.call(document) != objectClass; /** * Detect if string indexes are non-enumerable * (IE < 9, RingoJS, Rhino, Narwhal). * * @memberOf _.support * @type boolean */ support.nonEnumStrings = !propertyIsEnumerable.call('x', 0); /** * Detect if properties shadowing those on `Object.prototype` are * non-enumerable. * * In IE < 9 an object's own properties, shadowing non-enumerable ones, * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). * * @memberOf _.support * @type boolean */ support.nonEnumShadows = !/valueOf/.test(props); /** * Detect if own properties are iterated after inherited properties * (IE < 9). * * @memberOf _.support * @type boolean */ support.ownLast = props[0] != 'x'; /** * Detect if `Array#shift` and `Array#splice` augment array-like objects * correctly. * * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` * and `splice()` functions that fail to remove the last element, `value[0]`, * of array-like objects even though the `length` property is set to `0`. * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` * is buggy regardless of mode in IE < 9 and buggy in compatibility mode * in IE 9. * * @memberOf _.support * @type boolean */ support.spliceObjects = (splice.call(object, 0, 1), !object[0]); /** * Detect lack of support for accessing string characters by index. * * IE < 8 can't access characters by index. IE 8 can only access characters * by index on string literals, not string objects. * * @memberOf _.support * @type boolean */ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; /** * Detect if the DOM is supported. * * @memberOf _.support * @type boolean */ try { support.dom = document.createDocumentFragment().nodeType === 11; } catch(e) { support.dom = false; } /** * Detect if `arguments` object indexes are non-enumerable. * * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat * `arguments` object indexes as non-enumerable and fail `hasOwnProperty` * checks for indexes that exceed their function's formal parameters with * associated values of `0`. * * @memberOf _.support * @type boolean */ try { support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); } catch(e) { support.nonEnumArgs = true; } }(0, 0)); /** * By default, the template delimiters used by Lo-Dash are similar to those * in embedded Ruby (ERB). Change the following template settings to use * alternative delimiters. * * @static * @memberOf _ * @type Object */ lodash.templateSettings = { /** * Used to detect `data` property values to be HTML-escaped. * * @memberOf _.templateSettings * @type RegExp */ 'escape': reEscape, /** * Used to detect code to be evaluated. * * @memberOf _.templateSettings * @type RegExp */ 'evaluate': reEvaluate, /** * Used to detect `data` property values to inject. * * @memberOf _.templateSettings * @type RegExp */ 'interpolate': reInterpolate, /** * Used to reference the data object in the template text. * * @memberOf _.templateSettings * @type string */ 'variable': '', /** * Used to import variables into the compiled template. * * @memberOf _.templateSettings * @type Object */ 'imports': { /** * A reference to the `lodash` function. * * @memberOf _.templateSettings.imports * @type Function */ '_': lodash } }; /*------------------------------------------------------------------------*/ /** * Used by `_.defaults` to customize its `_.assign` use. * * @private * @param {*} objectValue The destination object property value. * @param {*} sourceValue The source object property value. * @returns {*} Returns the value to assign to the destination object. */ function assignDefaults(objectValue, sourceValue) { return typeof objectValue == 'undefined' ? sourceValue : objectValue; } /** * Used by `_.template` to customize its `_.assign` use. * * **Note:** This method is like `assignDefaults` except that it ignores * inherited property values when checking if a property is `undefined`. * * @private * @param {*} objectValue The destination object property value. * @param {*} sourceValue The source object property value. * @param {string} key The key associated with the object and source values. * @param {Object} object The destination object. * @returns {*} Returns the value to assign to the destination object. */ function assignOwnDefaults(objectValue, sourceValue, key, object) { return (typeof objectValue == 'undefined' || !hasOwnProperty.call(object, key)) ? sourceValue : objectValue; } /** * The base implementation of `_.assign` without support for argument juggling, * multiple sources, and `this` binding. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [customizer] The function to customize assigning values. * @returns {Object} Returns the destination object. */ function baseAssign(object, source, customizer) { var index = -1, props = keys(source), length = props.length; while (++index < length) { var key = props[index]; object[key] = customizer ? customizer(object[key], source[key], key, object, source) : source[key]; } return object; } /** * The base implementation of `_.bindAll` without support for individual * method name arguments. * * @private * @param {Object} object The object to bind and assign the bound methods to. * @param {string[]} methodNames The object method names to bind. * @returns {Object} Returns `object`. */ function baseBindAll(object, methodNames) { var index = -1, length = methodNames.length; while (++index < length) { var key = methodNames[index]; object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } /** * The base implementation of `_.callback` without support for creating * "_.pluck" and "_.where" style callbacks. * * @private * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. * @returns {Function} Returns the new function. */ function baseCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function') { if (typeof thisArg == 'undefined') { return func; } var data = getData(func); if (typeof data == 'undefined') { if (support.funcNames) { data = !func.name; } data = data || !support.funcDecomp; if (!data) { var source = fnToString.call(func); if (!support.funcNames) { data = !reFuncName.test(source); } if (!data) { // checks if `func` references the `this` keyword and stores the result data = reThis.test(source) || isNative(func); baseSetData(func, data); } } } // exit early if there are no `this` references or `func` is bound if (data === false || (data !== true && data[1] & BIND_FLAG)) { return func; } switch (argCount) { case 1: return function(value) { return func.call(thisArg, value); }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); }; case 4: return function(accumulator, value, index, collection) { return func.call(thisArg, accumulator, value, index, collection); }; case 5: return function(value, other, key, object, source) { return func.call(thisArg, value, other, key, object, source); }; } return function() { return func.apply(thisArg, arguments); }; } if (func == null) { return identity; } // handle "_.pluck" and "_.where" style callback shorthands return type == 'object' ? matches(func) : property(func); } /** * The base implementation of `_.clone` without support for argument juggling * and `this` binding. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep=false] Specify a deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates clones with source counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, isDeep, customizer, stackA, stackB) { var result = customizer ? customizer(value) : undefined; if (typeof result != 'undefined') { return result; } var isArr = isArray(value); result = value; if (isArr) { result = initArrayClone(value, isDeep); } else if (isObject(value)) { result = initObjectClone(value, isDeep); value = (isDeep && toString.call(result) == objectClass) ? value : result; } if (!isDeep || result === value) { return result; } // check for circular references and return corresponding clone stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == value) { return stackB[length]; } } // add the source value to the stack of traversed objects // and associate it with its clone stackA.push(value); stackB.push(result); // recursively populate clone (susceptible to call stack limits) (isArr ? arrayEach : baseForOwn)(value, function(valValue, key) { var valClone = customizer ? customizer(valValue, key) : undefined; result[key] = typeof valClone == 'undefined' ? baseClone(valValue, isDeep, null, stackA, stackB) : valClone; }); return result; } /** * The base implementation of `_.create` without support for assigning * properties to the created object. * * @private * @param {Object} prototype The object to inherit from. * @returns {Object} Returns the new object. */ function baseCreate(prototype) { return isObject(prototype) ? nativeCreate(prototype) : {}; } // fallback for environments without `Object.create` if (!nativeCreate) { baseCreate = (function() { function Object() {} return function(prototype) { if (isObject(prototype)) { Object.prototype = prototype; var result = new Object; Object.prototype = null; } return result || context.Object(); }; }()); } /** * The base implementation of `_.curry` and `_.curryRight` which handles * resolving the default arity of `func`. * * @private * @param {Function} func The function to curry. * @param {number} bitmask The bitmask of flags to compose. * @param {number} [arity=func.length] The arity of `func`. * @returns {Function} Returns the new curried function. */ function baseCurry(func, bitmask, arity) { if (typeof arity != 'number') { arity = arity == null ? (func ? func.length : 0) : nativeMax(+arity || 0, 0); } return createWrapper(func, bitmask, arity); } /** * The base implementation of `_.difference` which accepts a single array * of values to exclude. * * @private * @param {Array} array The array to inspect. * @param {Array} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. */ function baseDifference(array, values) { var length = array ? array.length : 0; if (!length) { return []; } var index = -1, indexOf = getIndexOf(), prereq = indexOf == baseIndexOf, isLarge = prereq && createCache && values && values.length >= 200, isCommon = prereq && !isLarge, result = [], valuesLength = values ? values.length : 0; if (isLarge) { indexOf = cacheIndexOf; values = createCache(values); } outer: while (++index < length) { var value = array[index]; if (isCommon && value === value) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { continue outer; } } result.push(value); } else if (indexOf(values, value) < 0) { result.push(value); } } return result; } /** * The base implementation of `_.forEach` without support for callback * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { return baseForOwn(collection, iteratee); } var index = -1, iterable = toObject(collection); while (++index < length) { if (iteratee(iterable[index], index, iterable) === false) { break; } } return collection; } /** * The base implementation of `_.forEachRight` without support for callback * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, iteratee) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { return baseForOwnRight(collection, iteratee); } var iterable = toObject(collection); while (length--) { if (iteratee(iterable[length], length, iterable) === false) { break; } } return collection; } /** * The base implementation of `_.every` without support for callback shorthands * or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns `true` if all elements passed the predicate check, * else `false` */ function baseEvery(collection, predicate) { var result = true; baseEach(collection, function(value, index, collection) { result = !!predicate(value, index, collection); return result; }); return result; } /** * The base implementation of `_.filter` without support for callback shorthands * or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { var result = []; baseEach(collection, function(value, index, collection) { if (predicate(value, index, collection)) { result.push(value); } }); return result; } /** * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, * without support for callback shorthands and `this` binding, which iterates * over `collection` using the provided `eachFunc`. * * @private * @param {Array|Object|string} collection The collection to search. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey=false] Specify returning the key of the found * element instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ function baseFind(collection, predicate, eachFunc, retKey) { var result; eachFunc(collection, function(value, key, collection) { if (predicate(value, key, collection)) { result = retKey ? key : value; return false; } }); return result; } /** * The base implementation of `_.flatten` with added support for restricting * flattening and specifying the start index. * * @private * @param {Array} array The array to flatten. * @param {boolean} [isDeep=false] Specify a deep flatten. * @param {boolean} [isStrict=false] Restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. * @returns {Array} Returns the new flattened array. */ function baseFlatten(array, isDeep, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (value && typeof value == 'object' && typeof value.length == 'number' && (isArray(value) || isArguments(value))) { // recursively flatten arrays (susceptible to call stack limits) if (isDeep) { value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, valLength = value.length; result.length += valLength; while (++valIndex < valLength) { result[++resIndex] = value[valIndex]; } } else if (!isStrict) { result[++resIndex] = value; } } return result; } /** * The base implementation of `baseForIn` and `baseForOwn` which iterates * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ function baseFor(object, iteratee, keysFunc) { object = toObject(object); var index = -1, props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; if (iteratee(object[key], key, object) === false) { break; } } return object; } /** * This function is like `baseFor` except that it iterates over properties * in the opposite order. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ function baseForRight(object, iteratee, keysFunc) { object = toObject(object); var props = keysFunc(object), length = props.length; while (length--) { var key = props[length]; if (iteratee(object[key], key, object) === false) { break; } } return object; } /** * The base implementation of `_.forIn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { return baseFor(object, iteratee, keysIn); } /** * The base implementation of `_.forOwn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return baseFor(object, iteratee, keys); } /** * The base implementation of `_.forOwnRight` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { return baseForRight(object, iteratee, keys); } /** * The base implementation of `_.functions` which creates an array of * `object` function property names filtered from those provided. * * @private * @param {Object} object The object to inspect. * @param {Array} props The property names to filter. * @returns {Array} Returns the new array of filtered property names. */ function baseFunctions(object, props) { var index = -1, length = props.length, resIndex = -1, result = []; while (++index < length) { var key = props[index]; if (isFunction(object[key])) { result[++resIndex] = key; } } return result; } /** * The base implementation of `_.isEqual`, without support for `thisArg` * binding, which allows partial "_.where" style comparisons. * * @private * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [customizer] The function to customize comparing values. * @param {boolean} [isWhere=false] Specify performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { var result = customizer && !stackA ? customizer(value, other) : undefined; if (typeof result != 'undefined') { return !!result; } // exit early for identical values if (value === other) { // treat `+0` vs. `-0` as not equal return value !== 0 || (1 / value == 1 / other); } var valType = typeof value, othType = typeof other; // exit early for unlike primitive values if (!(valType == 'number' && othType == 'number') && (value == null || other == null || (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) { return false; } var valClass = toString.call(value), valIsArg = valClass == argsClass, othClass = toString.call(other), othIsArg = othClass == argsClass; if (valIsArg) { valClass = objectClass; } if (othIsArg) { othClass = objectClass; } var valIsArr = arrayLikeClasses[valClass], valIsErr = valClass == errorClass, valIsObj = valClass == objectClass && !isHostObject(value), othIsObj = othClass == objectClass && !isHostObject(other); var isSameClass = valClass == othClass; if (isSameClass && valIsArr) { var valLength = value.length, othLength = other.length; if (valLength != othLength && !(isWhere && othLength > valLength)) { return false; } } else { // unwrap any `lodash` wrapped values var valWrapped = valIsObj && hasOwnProperty.call(value, '__wrapped__'), othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (valWrapped || othWrapped) { return baseIsEqual(valWrapped ? value.value() : value, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB); } if (!isSameClass) { return false; } if (valIsErr || valIsObj) { if (!support.argsClass) { valIsArg = isArguments(value); othIsArg = isArguments(other); } // in older versions of Opera, `arguments` objects have `Array` constructors var valCtor = valIsArg ? Object : value.constructor, othCtor = othIsArg ? Object : other.constructor; if (valIsErr) { // error objects of different types are not equal if (valCtor.prototype.name != othCtor.prototype.name) { return false; } } else { var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'), othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor'); if (valHasCtor != othHasCtor) { return false; } if (!valHasCtor) { // non `Object` object instances with different constructors are not equal if (valCtor != othCtor && !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) && ('constructor' in value && 'constructor' in other) ) { return false; } } } var valProps = valIsErr ? ['message', 'name'] : keys(value), othProps = valIsErr ? valProps : keys(other); if (valIsArg) { valProps.push('length'); } if (othIsArg) { othProps.push('length'); } valLength = valProps.length; othLength = othProps.length; if (valLength != othLength && !isWhere) { return false; } } else { switch (valClass) { case boolClass: case dateClass: // 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 +value == +other; case numberClass: // treat `NaN` vs. `NaN` as equal return (value != +value) ? other != +other // but treat `-0` vs. `+0` as not equal : (value == 0 ? ((1 / value) == (1 / other)) : value == +other); case regexpClass: case stringClass: // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and // treat strings primitives and string objects as equal return value == String(other); } return false; } } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) stackA || (stackA = []); stackB || (stackB = []); var index = stackA.length; while (index--) { if (stackA[index] == value) { return stackB[index] == other; } } // add `value` and `other` to the stack of traversed objects stackA.push(value); stackB.push(other); // recursively compare objects and arrays (susceptible to call stack limits) result = true; if (valIsArr) { // deep compare the contents, ignoring non-numeric properties while (result && ++index < valLength) { var valValue = value[index]; if (isWhere) { var othIndex = othLength; while (othIndex--) { result = baseIsEqual(valValue, other[othIndex], customizer, isWhere, stackA, stackB); if (result) { break; } } } else { var othValue = other[index]; result = customizer ? customizer(valValue, othValue, index) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(valValue, othValue, customizer, isWhere, stackA, stackB); } } } } else { while (result && ++index < valLength) { var key = valProps[index]; result = valIsErr || hasOwnProperty.call(other, key); if (result) { valValue = value[key]; othValue = other[key]; result = customizer ? customizer(valValue, othValue, key) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(valValue, othValue, customizer, isWhere, stackA, stackB); } } } } stackA.pop(); stackB.pop(); return !!result; } /** * The base implementation of `_.invoke` which requires additional arguments * be provided as an array of arguments rather than individually. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {Array} [args] The arguments to invoke the method with. * @returns {Array} Returns the array of results. */ function baseInvoke(collection, methodName, args) { var index = -1, isFunc = typeof methodName == 'function', length = collection ? collection.length : 0, result = []; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { result.length = length; } baseEach(collection, function(value) { var func = isFunc ? methodName : (value != null && value[methodName]); result[++index] = func ? func.apply(value, args) : undefined; }); return result; } /** * The base implementation of `_.map` without support for callback shorthands * or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { var result = []; baseEach(collection, function(value, key, collection) { result.push(iteratee(value, key, collection)); }); return result; } /** * The base implementation of `_.merge` without support for argument juggling, * multiple sources, and `this` binding. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [customizer] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns the destination object. */ function baseMerge(object, source, customizer, stackA, stackB) { var isSrcArr = isArrayLike(source); (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { var isArr = srcValue && isArrayLike(srcValue), isObj = srcValue && isPlainObject(srcValue), value = object[key]; if (!(isArr || isObj)) { result = customizer ? customizer(value, srcValue, key, object, source) : undefined; if (typeof result == 'undefined') { result = srcValue; } if (isSrcArr || typeof result != 'undefined') { object[key] = result; } return; } // avoid merging previously merged cyclic sources stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == srcValue) { object[key] = stackB[length]; return; } } var result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isDeep = typeof result == 'undefined'; if (isDeep) { result = isArr ? (isArray(value) ? value : []) : (isPlainObject(value) ? value : {}); } // add the source value to the stack of traversed objects // and associate it with its merged value stackA.push(srcValue); stackB.push(result); // recursively merge objects and arrays (susceptible to call stack limits) if (isDeep) { baseMerge(result, srcValue, customizer, stackA, stackB); } object[key] = result; }); return object; } /** * The base implementation of `_.partial` and `_.partialRight` which accepts * an array of arguments to partially apply and handles resolving the arity * of `func`. * * @private * @param {Function} func The function to partially apply arguments to. * @param {number} bitmask The bitmask of flags to compose. * @param {Array} args The arguments to be partially applied. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new partially applied function. */ function basePartial(func, bitmask, args, holders, thisArg) { if (func) { var data = getData(func), arity = data ? data[2] : func.length; arity = nativeMax(arity - args.length, 0); } return (bitmask & PARTIAL_FLAG) ? createWrapper(func, bitmask, arity, thisArg, args, holders) : createWrapper(func, bitmask, arity, thisArg, null, null, args, holders); } /** * The base implementation of `_.pullAt` without support for individual * index arguments. * * @private * @param {Array} array The array to modify. * @param {number[]} indexes The indexes of elements to remove. * @returns {Array} Returns the new array of removed elements. */ function basePullAt(array, indexes) { var length = indexes.length, result = baseAt(array, indexes); indexes.sort(baseCompareAscending); while (length--) { var index = parseFloat(indexes[length]); if (index != previous && index > -1 && index % 1 == 0) { var previous = index; splice.call(array, index, 1); } } return result; } /** * The base implementation of `_.random` without support for argument juggling * and returning floating-point numbers. * * @private * @param {number} min The minimum possible value. * @param {number} max The maximum possible value. * @returns {number} Returns the random number. */ function baseRandom(min, max) { return min + floor(nativeRandom() * (max - min + 1)); } /** * The base implementation of `_.reduce` and `_.reduceRight` without support * for callback shorthands or `this` binding, which iterates over `collection` * usingthe provided `eachFunc`. * * @private * @param {Array|Object|string} 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 {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection) }); return accumulator; } /** * The base implementation of `setData` without support for hot loop detection. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var baseSetData = !metaMap ? identity : function(func, data) { metaMap.set(func, data); return func; }; /** * The base implementation of `_.some` without support for callback shorthands * or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. */ function baseSome(collection, predicate) { var result; baseEach(collection, function(value, index, collection) { result = predicate(value, index, collection); return !result; }); return !!result; } /** * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` without * support for callback shorthands and `this` binding. * * @private * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest=false] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function baseSortedIndex(array, value, iteratee, retHighest) { var low = 0, high = array ? array.length : low; value = iteratee(value); var valIsNaN = value !== value, valIsUndef = typeof value == 'undefined'; while (low < high) { var mid = floor((low + high) / 2), computed = iteratee(array[mid]), isReflexive = computed === computed; if (valIsNaN) { var setLow = isReflexive || retHighest; } else if (valIsUndef) { setLow = isReflexive && (retHighest || typeof computed != 'undefined'); } else { setLow = retHighest ? (computed <= value) : (computed < value); } if (setLow) { low = mid + 1; } else { high = mid; } } return nativeMin(high, MAX_ARRAY_INDEX); } /** * The base implementation of `_.uniq` without support for callback shorthands * and `this` binding. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), length = array.length, prereq = indexOf == baseIndexOf, isLarge = prereq && createCache && length >= 200, isCommon = prereq && !isLarge, result = []; if (isLarge) { var seen = createCache(); indexOf = cacheIndexOf; } else { seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; if (isCommon && value === value) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } if (iteratee) { seen.push(computed); } result.push(value); } else if (indexOf(seen, computed) < 0) { if (iteratee || isLarge) { seen.push(computed); } result.push(value); } } return result; } /** * The base implementation of `_.values` and `_.valuesIn` which creates an * array of `object` property values corresponding to the property names * returned by `keysFunc`. * * @private * @param {Object} object The object to inspect. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns the array of property values. */ function baseValues(object, keysFunc) { var index = -1, props = keysFunc(object), length = props.length, result = Array(length); while (++index < length) { result[index] = object[props[index]]; } return result; } /** * Creates a clone of the given array buffer. * * @private * @param {ArrayBuffer} buffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ function bufferClone(buffer) { return bufferSlice.call(buffer, 0); } if (!bufferSlice) { // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array` bufferClone = !(ArrayBuffer && Uint8Array) ? identity : function(buffer) { var byteLength = buffer.byteLength, floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, result = new ArrayBuffer(byteLength); if (floatLength) { var view = new Float64Array(result, 0, floatLength); view.set(new Float64Array(buffer, 0, floatLength)); } if (byteLength != offset) { view = new Uint8Array(result, offset); view.set(new Uint8Array(buffer, offset)); } return result; }; } /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private * @param {Array} partialArgs The arguments to prepend to those provided. * @param {Array} partialHolders The `partialArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. * @returns {Array} Returns the new array of composed arguments. */ function composeArgs(partialArgs, partialHolders, args) { var holdersLength = partialHolders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partialArgs.length, result = Array(argsLength + leftLength); while (++leftIndex < leftLength) { result[leftIndex] = partialArgs[leftIndex]; } while (++argsIndex < holdersLength) { result[partialHolders[argsIndex]] = args[argsIndex]; } while (argsLength--) { result[leftIndex++] = args[argsIndex++]; } return result; } /** * This function is like `composeArgs` except that the arguments composition * is tailored for `_.partialRight`. * * @private * @param {Array} partialRightArgs The arguments to append to those provided. * @param {Array} partialHolders The `partialRightArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. * @returns {Array} Returns the new array of composed arguments. */ function composeArgsRight(partialRightArgs, partialRightHolders, args) { var holdersIndex = -1, holdersLength = partialRightHolders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partialRightArgs.length, result = Array(argsLength + rightLength); while (++argsIndex < argsLength) { result[argsIndex] = args[argsIndex]; } var pad = argsIndex; while (++rightIndex < rightLength) { result[pad + rightIndex] = partialRightArgs[rightIndex]; } while (++holdersIndex < holdersLength) { result[pad + partialRightHolders[holdersIndex]] = args[argsIndex++]; } return result; } /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection * through `iteratee`. The given setter function sets the keys and values of * the accumulator object. If `initializer` is provided it is used to initialize * the accumulator object. * * @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. * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { return function(collection, iteratee, thisArg) { iteratee = getCallback(iteratee, thisArg, 3); var result = initializer ? initializer() : {}; if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { setter(result, value, iteratee(value, key, collection), collection); }); } return result; }; } /** * Creates a function that assigns properties of source object(s) to a given * destination object. * * @private * @param {Function} assigner The function to handle assigning values. * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { return function() { var length = arguments.length, object = arguments[0]; if (object == null || length < 2) { return object; } // enables use as a callback for functions like `_.reduce` var type = typeof arguments[2]; if ((type == 'number' || type == 'string') && arguments[3] && arguments[3][arguments[2]] === arguments[1]) { length = 2; } // juggle arguments if (length > 3 && typeof arguments[length - 2] == 'function') { var customizer = baseCallback(arguments[--length - 1], arguments[length--], 5); } else if (length > 2 && typeof arguments[length - 1] == 'function') { customizer = arguments[--length]; } var index = 0; while (++index < length) { assigner(object, arguments[index], customizer); } return object; }; } /** * Creates a function that wraps `func` and invokes it with the `this` * binding of `thisArg`. * * @private * @param {Function} func The function to bind. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new wrapped function. */ function createBindWrapper(func, thisArg) { var Ctor = createCtorWrapper(func); function wrapper() { return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); } return wrapper; } /** * Creates a cache object to optimize linear searches of large arrays. * * @private * @param {Array} [array=[]] The array to search. * @returns {Object} Returns the new cache object. */ var createCache = Set && function(array) { var cache = new Set, length = array ? array.length : 0; cache.push = cache.add; while (length--) { cache.push(array[length]); } return cache; }; /** * Creates a function that produces compound words out of the words in a * given string. * * @private * @param {Function} callback The function invoked to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { return function(string) { var index = -1, array = words(deburr(string)), length = array.length, result = ''; while (++index < length) { result = callback(result, array[index], index, words); } return result; }; } /** * Creates a function that produces an instance of `Ctor` regardless of * whether it was invoked as part of a `new` expression or by `call` or `apply`. * * @private * @param {Function} Ctor The constructor to wrap. * @returns {Function} Returns the new function. */ function createCtorWrapper(Ctor) { return function() { var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, arguments); // mimic the constructor's `return` behavior // http://es5.github.io/#x13.2.2 return isObject(result) ? result : thisBinding; }; } /** * Creates a function that wraps `func` and invokes it with optional `this` * binding of, partial application, and currying. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {number} arity The arity of `func`. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partialArgs] The arguments to prepend to those provided to the new function. * @param {Array} [partialHolders] The `partialArgs` placeholder indexes. * @param {Array} [partialRightArgs] The arguments to append to those provided to the new function. * @param {Array} [partialRightHolders] The `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ function createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG; var Ctor = !isBindKey && createCtorWrapper(func), key = func; function wrapper() { var length = arguments.length, index = length, args = Array(length); while (index--) { args[index] = arguments[index]; } if (partialArgs) { args = composeArgs(partialArgs, partialHolders, args); } if (partialRightArgs) { args = composeArgsRight(partialRightArgs, partialRightHolders, args); } if (isCurry || isCurryRight) { var placeholder = wrapper.placeholder, holders = replaceHolders(args, placeholder); length -= holders.length; if (length < arity) { var newArity = nativeMax(arity - length, 0), newPartialArgs = isCurry ? args : null, newPartialHolders = isCurry ? holders : null, newPartialRightArgs = isCurry ? null : args, newPartialRightHolders = isCurry ? null : holders; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } var result = createHybridWrapper(func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders); result.placeholder = placeholder; return setData(result, [func, bitmask, newArity, thisArg, newPartialArgs, newPartialHolders, newPartialRightArgs, newPartialRightHolders]); } } var thisBinding = isBind ? thisArg : this; if (isBindKey) { func = thisBinding[key]; } return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); } return wrapper; } /** * Creates the pad required for `string` based on the given padding length. * The `chars` string may be truncated if the number of padding characters * exceeds the padding length. * * @private * @param {string} string The string to create padding for. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the pad for `string`. */ function createPad(string, length, chars) { var strLength = string.length; length = +length; if (strLength >= length || !nativeIsFinite(length)) { return ''; } var padLength = length - strLength; chars = chars == null ? ' ' : String(chars); return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); } /** * Creates a function that wraps `func` and invokes it with the optional `this` * binding of `thisArg` and the `partialArgs` prepended to those provided to * the wrapper. * * @private * @param {Function} func The function to partially apply arguments to. * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {Array} partialArgs The arguments to prepend to those provided to the new function. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new bound function. */ function createPartialWrapper(func, bitmask, partialArgs, thisArg) { var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partialArgs.length, args = Array(argsLength + leftLength); while (++leftIndex < leftLength) { args[leftIndex] = partialArgs[leftIndex]; } while (argsLength--) { args[leftIndex++] = arguments[++argsIndex]; } return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); } return wrapper; } /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` * 4 - `_.curry` * 8 - `_.curryRight` * 16 - `_.curry` or `_.curryRight` of a bound function * 32 - `_.partial` * 64 - `_.partialRight` * @param {number} arity The arity of `func`. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partialArgs] The arguments to prepend to those provided to the new function. * @param {Array} [partialHolders] The `partialArgs` placeholder indexes. * @param {Array} [partialRightArgs] The arguments to append to those provided to the new function. * @param {Array} [partialRightHolders] The `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders) { var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && !isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } var isPartial = bitmask & PARTIAL_FLAG; if (isPartial && !partialArgs.length) { bitmask &= ~PARTIAL_FLAG; isPartial = false; partialArgs = partialHolders = null; } var isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (isPartialRight && !partialRightArgs.length) { bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = false; partialRightArgs = partialRightHolders = null; } var data = (data = !isBindKey && getData(func)) && data !== true && data; if (data) { var funcBitmask = data[1], funcIsBind = funcBitmask & BIND_FLAG, isBind = bitmask & BIND_FLAG; // use metadata `func` and merge bitmasks func = data[0]; bitmask |= funcBitmask; // use metadata `arity` if not provided if (arity == null) { arity = data[2]; } // use metadata `thisArg` if available if (funcIsBind) { thisArg = data[3]; } // set if currying a bound function if (!isBind && funcIsBind) { bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments var funcArgs = data[4]; if (funcArgs) { var funcHolders = data[5]; partialArgs = isPartial ? composeArgs(funcArgs, funcHolders, partialArgs) : baseSlice(funcArgs); partialHolders = isPartial ? replaceHolders(partialArgs, PLACEHOLDER) : baseSlice(funcHolders); } // prepend partial right arguments funcArgs = data[6]; if (funcArgs) { funcHolders = data[7]; partialRightArgs = isPartialRight ? composeArgsRight(funcArgs, funcHolders, partialRightArgs) : baseSlice(funcArgs); partialRightHolders = isPartialRight ? replaceHolders(partialRightArgs, PLACEHOLDER) : baseSlice(funcHolders); } } if (arity == null) { arity = isBindKey ? 0 : func.length; } if (bitmask == BIND_FLAG) { var result = createBindWrapper(func, thisArg); } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !partialHolders.length) { result = createPartialWrapper(func, bitmask, partialArgs, thisArg); } else { result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); } var setter = data ? baseSetData : setData; return setter(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); } /** * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns * the `baseCallback` function. If arguments are provided the chosen function * is invoked with them and its result is returned. * * @private * @returns {Function} Returns the chosen function or its result. */ function getCallback(func, thisArg, argCount) { var result = lodash.callback || callback; result = result === callback ? baseCallback : result; return argCount ? result(func, thisArg, argCount) : result; } /** * Gets metadata for `func`. * * @private * @param {Function} func The function to query. * @returns {*} Returns the metadata for `func`. */ var getData = !metaMap ? noop : function(func) { return metaMap.get(func); }; /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. */ function getIndexOf(collection, target, fromIndex) { var result = lodash.indexOf || indexOf; result = result === indexOf ? baseIndexOf : result; return collection ? result(collection, target, fromIndex) : result; } /** * Initializes an array clone. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep=false] Specify a deep clone. * @returns {*} Returns the initialized clone value. */ function initArrayClone(array, isDeep) { var index = -1, length = array.length, result = array.constructor(length); if (!isDeep) { while (++index < length) { result[index] = array[index]; } } // add array properties assigned by `RegExp#exec` if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { result.index = array.index; result.input = array.input; } return result; } /** * Initializes an object clone. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep=false] Specify a deep clone. * @returns {*} Returns the initialized clone value. */ function initObjectClone(object, isDeep) { var className = toString.call(object); if (!cloneableClasses[className] || isHostObject(object)) { return object; } var Ctor = object.constructor, isArgs = className == argsClass || (!support.argsClass && isArguments(object)), isObj = className == objectClass; if (isObj && !(isFunction(Ctor) && (Ctor instanceof Ctor))) { Ctor = Object; } if (isArgs || isObj) { var result = isDeep ? new Ctor : baseAssign(new Ctor, object); if (isArgs) { result.length = object.length; } return result; } switch (className) { case arrayBufferClass: return bufferClone(object); case boolClass: case dateClass: return new Ctor(+object); case float32Class: case float64Class: case int8Class: case int16Class: case int32Class: case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class: // Safari 5 mobile incorrectly has `Object` as the constructor if (Ctor instanceof Ctor) { Ctor = ctorByClass[className]; } var buffer = object.buffer; return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); case numberClass: case stringClass: return new Ctor(object); case regexpClass: result = Ctor(object.source, reFlags.exec(object)); result.lastIndex = object.lastIndex; } return result; } /** * Checks if `value` is an array-like object. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`. */ function isArrayLike(value) { return (value && typeof value == 'object' && typeof value.length == 'number' && arrayLikeClasses[toString.call(value)]) || false; } /** * 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 && (value === 0 ? ((1 / value) > 0) : !isObject(value)); } /** * A specialized version of `_.pick` that picks `object` properties * specified by the `props` array. * * @private * @param {Object} object The source object. * @param {string[]} props The property names to pick. * @returns {Object} Returns the new object. */ function pickByArray(object, props) { var index = -1, length = props.length, result = {}; while (++index < length) { var key = props[index]; if (key in object) { result[key] = object[key]; } } return result; } /** * A specialized version of `_.pick` that picks `object` properties * the predicate returns truthy for. * * @private * @param {Object} object The source object. * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { var result = {}; baseForIn(object, function(value, key, object) { if (predicate(value, key, object)) { result[key] = value; } }); return result; } /** * Sets metadata for `func`. * * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity * function to avoid garbage collection pauses. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var setData = (function() { var count = 0, lastCalled = 0; return function(key, value) { var stamp = now ? now() : 0, remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { if (++count >= HOT_COUNT) { return key; } } else { count = 0; } return baseSetData(key, value); }; }()); /** * A fallback implementation of `_.isPlainObject` which checks if `value` * is an object created by the `Object` constructor or has a `[[Prototype]]` * of `null`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { var Ctor, result; // exit early for non `Object` objects if (!(value && typeof value == 'object' && toString.call(value) == objectClass && !isHostObject(value)) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, isFunction(Ctor) && !(Ctor instanceof Ctor))) || (!support.argsClass && isArguments(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first // iterated property is an object's own property then there are no inherited // enumerable properties. if (support.ownLast) { baseForIn(value, function(value, key, object) { result = hasOwnProperty.call(object, key); return false; }); return result !== false; } // In most environments an object's own properties are iterated before // its inherited properties. If the last iterated property is an object's // own property then there are no inherited enumerable properties. baseForIn(value, function(value, key) { result = key; }); return typeof result == 'undefined' || hasOwnProperty.call(value, result); } /** * A fallback implementation of `Object.keys` which creates an array of the * own enumerable property names of `object`. * * @private * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property names. */ function shimKeys(object) { var keyIndex, index = -1, props = keysIn(object), length = props.length, objLength = length && object.length, maxIndex = objLength - 1, result = []; var allowIndexes = typeof objLength == 'number' && objLength > 0 && (isArray(object) || (support.nonEnumArgs && isArguments(object)) || (support.nonEnumStrings && isString(object))); while (++index < length) { var key = props[index]; if ((allowIndexes && (keyIndex = +key, keyIndex > -1 && keyIndex <= maxIndex && keyIndex % 1 == 0)) || hasOwnProperty.call(object, key)) { result.push(key); } } return result; } /** * Converts `value` to an array-like object if it is not one. * * @private * @param {*} value The value to process. * @returns {Array|Object} Returns the array-like object. */ function toIterable(value) { if (value == null) { return []; } var length = value.length; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { return values(value); } if (support.unindexedChars && isString(value)) { return value.split(''); } return isObject(value) ? value : Object(value); } /** * Converts `value` to an object if it is not one. * * @private * @param {*} value The value to process. * @returns {Object} Returns the object. */ function toObject(value) { if (support.unindexedChars && isString(value)) { var index = -1, length = value.length, result = Object(value); while (++index < length) { result[index] = value.charAt(index); } return result; } return isObject(value) ? value : Object(value); } /*------------------------------------------------------------------------*/ /** * Creates an array of elements split into groups the length of `size`. * If `collection` can't be split evenly, the final chunk will be the remaining * elements. * * @static * @memberOf _ * @category Array * @param {Array} array The array to process. * @param {numer} [size=1] The length of each chunk. * @returns {Array} Returns the new array containing chunks. * @example * * _.chunk(['a', 'b', 'c', 'd'], 2); * // => [['a', 'b'], ['c', 'd']] * * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ function chunk(array, size) { var index = 0, length = array ? array.length : 0, resIndex = -1, result = []; size = typeof size == 'undefined' ? 1 : nativeMax(+size || 1, 1); while (index < length) { result[++resIndex] = slice(array, index, (index += size)); } return result; } /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are all falsey. * * @static * @memberOf _ * @category Array * @param {Array} array The array to compact. * @returns {Array} Returns the new array of filtered values. * @example * * _.compact([0, 1, false, 2, '', 3]); * // => [1, 2, 3] */ function compact(array) { var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (value) { result[++resIndex] = value; } } return result; } /** * Creates an array excluding all values of the provided arrays using * `SameValueZero` for equality comparisons. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example * * _.difference([1, 2, 3], [5, 2, 10]); * // => [1, 3] */ function difference() { var index = -1, length = arguments.length; while (++index < length) { var value = arguments[index]; if (isArray(value) || isArguments(value)) { break; } } return baseDifference(arguments[index], baseFlatten(arguments, false, true, ++index)); } /** * Creates a slice of `array` with `n` elements dropped from the beginning. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.drop([1, 2, 3], 1); * // => [2, 3] * * _.drop([1, 2, 3], 2); * // => [3] * * _.drop([1, 2, 3], 5); * // => [] * * _.drop([1, 2, 3], 0); * // => [1, 2, 3] */ function drop(array, n, guard) { n = (n == null || guard) ? 1 : n; return slice(array, n < 0 ? 0 : n); } /** * Creates a slice of `array` with `n` elements dropped from the end. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRight([1, 2, 3], 1); * // => [1, 2] * * _.dropRight([1, 2, 3], 2); * // => [1] * * _.dropRight([1, 2, 3], 5); * // => [] * * _.dropRight([1, 2, 3], 0); * // => [1, 2, 3] */ function dropRight(array, n, guard) { var length = array ? array.length : 0; n = (n == null || guard) ? 1 : n; n = length - (n || 0); return slice(array, 0, n < 0 ? 0 : n); } /** * Creates a slice of `array` excluding elements dropped from the end. * Elements are dropped until the predicate returns falsey. The predicate is * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [1] * * var users = [ * { 'user': 'barney', 'employer': 'slate' }, * { 'user': 'fred', 'employer': 'slate', 'blocked': true }, * { 'user': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.dropRightWhile(users, 'blocked'), 'user'); * // => ['barney'] * * // using "_.where" callback shorthand * _.pluck(_.dropRightWhile(users, { 'employer': 'na' }), 'user'); * // => ['barney', 'fred'] */ function dropRightWhile(array, predicate, thisArg) { var length = array ? array.length : 0, index = length; predicate = getCallback(predicate, thisArg, 3); while (index-- && predicate(array[index], index, array)) {} return slice(array, 0, index + 1); } /** * Creates a slice of `array` excluding elements dropped from the beginning. * Elements are dropped until the predicate returns falsey. The predicate is * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropWhile([1, 2, 3], function(n) { return n < 3; }); * // => [3] * * var users = [ * { 'user': 'barney', 'employer': 'slate', 'blocked': true }, * { 'user': 'fred', 'employer': 'slate' }, * { 'user': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.dropWhile(users, 'blocked'), 'user'); * // => ['fred', 'pebbles'] * * // using "_.where" callback shorthand * _.pluck(_.dropWhile(users, { 'employer': 'slate' }), 'user'); * // => ['pebbles'] */ function dropWhile(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) {} return slice(array, index); } /** * This method is like `_.find` except that it returns the index of the first * element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40, 'blocked': true }, * { 'user': 'pebbles', 'age': 1 } * ]; * * _.findIndex(users, function(chr) { * return chr.age < 20; * }); * // => 2 * * // using "_.where" callback shorthand * _.findIndex(users, { 'age': 36 }); * // => 0 * * // using "_.pluck" callback shorthand * _.findIndex(users, 'blocked'); * // => 1 */ function findIndex(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); while (++index < length) { if (predicate(array[index], index, array)) { return index; } } return -1; } /** * This method is like `_.findIndex` except that it iterates over elements * of `collection` from right to left. * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'blocked': true }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'pebbles', 'age': 1, 'blocked': true } * ]; * * _.findLastIndex(users, function(chr) { * return chr.age > 30; * }); * // => 1 * * // using "_.where" callback shorthand * _.findLastIndex(users, { 'age': 36 }); * // => 0 * * // using "_.pluck" callback shorthand * _.findLastIndex(users, 'blocked'); * // => 2 */ function findLastIndex(array, predicate, thisArg) { var length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); while (length--) { if (predicate(array[length], length, array)) { return length; } } return -1; } /** * Gets the first element of `array`. * * @static * @memberOf _ * @alias head * @category Array * @param {Array} array The array to query. * @returns {*} Returns the first element of `array`. * @example * * _.first([1, 2, 3]); * // => 1 * * _.first([]); * // => undefined */ function first(array) { return array ? array[0] : undefined; } /** * Flattens a nested array. If `isDeep` is `true` the array is recursively * flattened, otherwise it is only flattened a single level. * * @static * @memberOf _ * @category Array * @param {Array} array The array to flatten. * @param {boolean} [isDeep=false] Specify a deep flatten. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the new flattened array. * @example * * _.flatten([1, [2], [3, [[4]]]]); * // => [1, 2, 3, [[4]]]; * * // using `isDeep` * _.flatten([1, [2], [3, [[4]]]], true); * // => [1, 2, 3, 4]; */ function flatten(array, isDeep, guard) { var length = array ? array.length : 0; if (!length) { return []; } // enables use as a callback for functions like `_.map` var type = typeof isDeep; if ((type == 'number' || type == 'string') && guard && guard[isDeep] === array) { isDeep = false; } return baseFlatten(array, isDeep); } /** * Recursively flattens a nested array. * * @static * @memberOf _ * @category Array * @param {Array} array The array to recursively flatten. * @returns {Array} Returns the new flattened array. * @example * * _.flattenDeep([1, [2], [3, [[4]]]]); * // => [1, 2, 3, 4]; */ function flattenDeep(array) { var length = array ? array.length : 0; return length ? baseFlatten(array, true) : []; } /** * Gets the index at which the first occurrence of `value` is found in `array` * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, * it is used as the offset from the end of the collection. If `array` is * sorted providing `true` for `fromIndex` performs a faster binary search. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=0] The index to search from or `true` * to perform a binary search on a sorted array. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.indexOf([1, 2, 3, 1, 2, 3], 2); * // => 1 * * // using `fromIndex` * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); * // => 4 * * // performing a binary search * _.indexOf([4, 4, 5, 5, 6, 6], 5, true); * // => 2 */ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } else if (fromIndex) { var index = sortedIndex(array, value); return (length && array[index] === value) ? index : -1; } return baseIndexOf(array, value, fromIndex); } /** * Gets all but the last element of `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.initial([1, 2, 3]); * // => [1, 2] */ function initial(array) { var length = array ? array.length : 0; return slice(array, 0, length ? length - 1 : 0); } /** * Creates an array of unique values present in all provided arrays using * `SameValueZero` for equality comparisons. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of shared values. * @example * * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); * // => [1, 2] */ function intersection() { var args = [], argsIndex = -1, argsLength = arguments.length, caches = [], indexOf = getIndexOf(), prereq = createCache && indexOf == baseIndexOf; while (++argsIndex < argsLength) { var value = arguments[argsIndex]; if (isArray(value) || isArguments(value)) { args.push(value); caches.push(prereq && value.length >= 120 && createCache(argsIndex && value)); } } argsLength = args.length; var array = args[0], index = -1, length = array ? array.length : 0, result = [], seen = caches[0]; outer: while (++index < length) { value = array[index]; if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) { argsIndex = argsLength; while (--argsIndex) { var cache = caches[argsIndex]; if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { continue outer; } } if (seen) { seen.push(value); } result.push(value); } } 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; } /** * This method is like `_.indexOf` except that it iterates over elements of * `array` from right to left. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=array.length-1] The index to search from * or `true` to perform a binary search on a sorted array. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); * // => 4 * * // using `fromIndex` * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); * // => 1 * * // performing a binary search * _.lastIndexOf([4, 4, 5, 5, 6, 6], 5, true); * // => 3 */ function lastIndexOf(array, value, fromIndex) { var length = array ? array.length : 0, index = length; if (typeof fromIndex == 'number') { index = (fromIndex < 0 ? nativeMax(index + fromIndex, 0) : nativeMin(fromIndex || 0, index - 1)) + 1; } else if (fromIndex) { index = sortedLastIndex(array, value) - 1; return (length && array[index] === value) ? index : -1; } var isReflexive = value === value; while (index--) { var other = array[index]; if ((isReflexive ? other === value : other !== other)) { return index; } } return -1; } /** * Removes all provided values from `array` using `SameValueZero` for equality * comparisons. * * **Notes:** * - Unlike `_.without`, this method mutates `array`. * - `SameValueZero` is like strict equality, e.g. `===`, except that `NaN` matches `NaN`. * See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to modify. * @param {...*} [values] The values to remove. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3, 1, 2, 3]; * _.pull(array, 2, 3); * console.log(array); * // => [1, 1] */ function pull() { var array = arguments[0], index = 0, indexOf = getIndexOf(), length = arguments.length; while (++index < length) { var fromIndex = 0, value = arguments[index]; while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { splice.call(array, fromIndex, 1); } } return array; } /** * Removes elements from `array` corresponding to the specified indexes and * returns an array of the removed elements. Indexes may be specified as an * array of indexes or as individual arguments. * * **Note:** Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to modify. * @param {...(number|number[])} [indexes] The indexes of elements to remove, * specified as individual indexes or arrays of indexes. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [5, 10, 15, 20]; * var evens = _.pullAt(array, [1, 3]); * * console.log(array); * // => [5, 15] * * console.log(evens); * // => [10, 20] */ function pullAt(array) { return basePullAt(array, baseFlatten(arguments, false, false, 1)); } /** * Removes all elements from `array` that the predicate returns truthy for * and returns an array of the removed elements. The predicate is bound to * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * **Note:** Unlike `_.filter`, this method mutates `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to modify. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [1, 2, 3, 4]; * var evens = _.remove(array, function(n) { return n % 2 == 0; }); * * console.log(array); * // => [1, 3] * * console.log(evens); * // => [2, 4] */ function remove(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0, result = []; predicate = getCallback(predicate, thisArg, 3); while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result.push(value); splice.call(array, index--, 1); length--; } } return result; } /** * Gets all but the first element of `array`. * * @static * @memberOf _ * @alias tail * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.rest([1, 2, 3]); * // => [2, 3] */ function rest(array) { return slice(array, 1); } /** * Slices `array` from the `start` index up to, but not including, the `end` index. * * **Note:** This function is used instead of `Array#slice` to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @static * @memberOf _ * @category Array * @param {Array} array The array to slice. * @param {number} [start=0] The start index. * @param {number} [end=array.length] The end index. * @returns {Array} Returns the slice of `array`. */ function slice(array, start, end) { var index = -1, length = array ? array.length : 0; start = start == null ? 0 : (+start || 0); if (start < 0) { start = -start > length ? 0 : (length + start); } end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); if (end < 0) { end += length; } if (end && end == length && !start) { return baseSlice(array); } length = start > end ? 0 : (end - start); var result = Array(length); while (++index < length) { result[index] = array[index + start]; } return result; } /** * Uses a binary search to determine the lowest index at which a value should * be inserted into a given sorted array in order to maintain the sort order * of the array. If an iteratee function is provided it is invoked for `value` * and each element of `array` to compute their sort ranking. The iteratee * function is bound to `thisArg` and invoked with one argument; (value). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedIndex([30, 50], 40); * // => 1 * * _.sortedIndex([4, 4, 5, 5, 6, 6], 5); * // => 2 * * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * * // using an iteratee function * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { * return this.data[word]; * }, dict); * // => 1 * * // using "_.pluck" callback shorthand * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ function sortedIndex(array, value, iteratee, thisArg) { iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); return baseSortedIndex(array, value, iteratee); } /** * This method is like `_.sortedIndex` except that it returns the highest * index at which a value should be inserted into a given sorted array in * order to maintain the sort order of the array. * * @static * @memberOf _ * @category Array * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedLastIndex([4, 4, 5, 5, 6, 6], 5); * // => 4 */ function sortedLastIndex(array, value, iteratee, thisArg) { iteratee = iteratee == null ? identity : getCallback(iteratee, thisArg, 1); return baseSortedIndex(array, value, iteratee, true); } /** * Creates a slice of `array` with `n` elements taken from the beginning. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.take([1, 2, 3], 1); * // => [1] * * _.take([1, 2, 3], 2); * // => [1, 2] * * _.take([1, 2, 3], 5); * // => [1, 2, 3] * * _.take([1, 2, 3], 0); * // => [] */ function take(array, n, guard) { n = (n == null || guard) ? 1 : n; return slice(array, 0, n < 0 ? 0 : n); } /** * Creates a slice of `array` with `n` elements taken from the end. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRight([1, 2, 3], 1); * // => [3] * * _.takeRight([1, 2, 3], 2); * // => [2, 3] * * _.takeRight([1, 2, 3], 5); * // => [1, 2, 3] * * _.takeRight([1, 2, 3], 0); * // => [] */ function takeRight(array, n, guard) { var length = array ? array.length : 0; n = (n == null || guard) ? 1 : n; n = length - (n || 0); return slice(array, n < 0 ? 0 : n); } /** * Creates a slice of `array` with elements taken from the end. Elements are * taken until the predicate returns falsey. The predicate is bound to `thisArg` * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [2, 3] * * var users = [ * { 'user': 'barney', 'employer': 'slate' }, * { 'user': 'fred', 'employer': 'slate', 'blocked': true }, * { 'user': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.takeRightWhile(users, 'blocked'), 'user'); * // => ['fred', 'pebbles'] * * // using "_.where" callback shorthand * _.pluck(_.takeRightWhile(users, { 'employer': 'na' }), 'user'); * // => ['pebbles'] */ function takeRightWhile(array, predicate, thisArg) { var length = array ? array.length : 0, index = length; predicate = getCallback(predicate, thisArg, 3); while (index-- && predicate(array[index], index, array)) {} return slice(array, index + 1); } /** * Creates a slice of `array` with elements taken from the beginning. Elements * are taken until the predicate returns falsey. The predicate is bound to * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeWhile([1, 2, 3], function(n) { return n < 3; }); * // => [1, 2] * * var users = [ * { 'user': 'barney', 'employer': 'slate', 'blocked': true }, * { 'user': 'fred', 'employer': 'slate' }, * { 'user': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.takeWhile(users, 'blocked'), 'user'); * // => ['barney'] * * // using "_.where" callback shorthand * _.pluck(_.takeWhile(users, { 'employer': 'slate' }), 'user'); * // => ['barney', 'fred'] */ function takeWhile(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) {} return slice(array, 0, index); } /** * Creates an array of unique values, in order, of the provided arrays using * `SameValueZero` for equality comparisons. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of combined values. * @example * * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); * // => [1, 2, 3, 5, 4] */ function union() { return baseUniq(baseFlatten(arguments, false, true)); } /** * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster * search algorithm for sorted arrays. If an iteratee function is provided it * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @alias unique * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted=false] Specify the array is sorted. * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new duplicate-value-free array. * @example * * _.uniq([1, 2, 1]); * // => [1, 2] * * // using `isSorted` * _.uniq([1, 1, 2], true); * // => [1, 2] * * // using an iteratee function * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); * // => [1, 2.5] * * // using "_.pluck" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ function uniq(array, isSorted, iteratee, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } // juggle arguments var type = typeof isSorted; if (type != 'boolean' && isSorted != null) { thisArg = iteratee; iteratee = isSorted; isSorted = false; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === array) { iteratee = null; } } if (iteratee != null) { iteratee = getCallback(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); } /** * This method is like `_.zip` except that it accepts an array of grouped * elements and creates an array regrouping the elements to their pre `_.zip` * configuration. * * @static * @memberOf _ * @category Array * @param {Array} array The array of grouped elements to process. * @returns {Array} Returns the new array of regrouped elements. * @example * * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] * * _.unzip(zipped); * // => [['fred', 'barney'], [30, 40], [true, false]] */ function unzip(array) { var index = -1, length = isObject(length = max(array, 'length')) && length.length || 0, result = Array(length); while (++index < length) { result[index] = pluck(array, index); } return result; } /** * Creates an array excluding all provided values using `SameValueZero` for * equality comparisons. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to filter. * @param {...*} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. * @example * * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ function without(array) { return baseDifference(array, slice(arguments, 1)); } /** * Creates an array that is the symmetric difference of the provided arrays. * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for * more details. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of values. * @example * * _.xor([1, 2, 3], [5, 2, 1, 4]); * // => [3, 5, 4] * * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); * // => [1, 4, 5] */ function xor() { var index = -1, length = arguments.length; while (++index < length) { var array = arguments[index]; if (isArray(array) || isArguments(array)) { var result = result ? baseDifference(result, array).concat(baseDifference(array, result)) : array; } } return result ? baseUniq(result) : []; } /** * Creates an array of grouped elements, the first of which contains the first * elements of the given arrays, the second of which contains the second elements * of the given arrays, and so on. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to process. * @returns {Array} Returns the new array of grouped elements. * @example * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] */ function zip() { var length = arguments.length, array = Array(length); while (length--) { array[length] = arguments[length]; } return unzip(array); } /** * Creates an object composed from arrays of property names and values. Provide * either a single two dimensional array, e.g. `[[key1, value1], [key2, value2]]` * or two arrays, one of property names and one of corresponding values. * * @static * @memberOf _ * @alias object * @category Array * @param {Array} props The property names. * @param {Array} [vals=[]] The property values. * @returns {Object} Returns the new object. * @example * * _.zipObject(['fred', 'barney'], [30, 40]); * // => { 'fred': 30, 'barney': 40 } */ function zipObject(props, vals) { var index = -1, length = props ? props.length : 0, result = {}; if (!vals && length && !isArray(props[0])) { vals = []; } while (++index < length) { var key = props[index]; if (vals) { result[key] = vals[index]; } else if (key) { result[key[0]] = key[1]; } } return result; } /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object that wraps `value` with explicit method * chaining enabled. * * @static * @memberOf _ * @category Chain * @param {*} value The value to wrap. * @returns {Object} Returns the new wrapper object. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'pebbles', 'age': 1 } * ]; * * var youngest = _.chain(users) * .sortBy('age') * .map(function(chr) { return chr.user + ' is ' + chr.age; }) * .first() * .value(); * // => 'pebbles is 1' */ function chain(value) { var result = lodash(value); result.__chain__ = true; return result; } /** * This method invokes `interceptor` and returns `value`. The interceptor is * bound to `thisArg` and invoked with one argument; (value). The purpose of * this method is to "tap into" a method chain in order to perform operations * on intermediate results within the chain. * * @static * @memberOf _ * @category Chain * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns `value`. * @example * * _([1, 2, 3]) * .tap(function(array) { array.pop(); }) * .reverse() * .value(); * // => [2, 1] */ function tap(value, interceptor, thisArg) { interceptor.call(thisArg, value); return value; } /** * This method is like `_.tap` except that it returns the result of `interceptor`. * * @static * @memberOf _ * @category Chain * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns the result of `interceptor`. * @example * * _([1, 2, 3]) * .last() * .thru(function(value) { return [value]; }) * .value(); * // => [3] */ function thru(value, interceptor, thisArg) { return interceptor.call(thisArg, value); } /** * Enables explicit method chaining on the wrapper object. * * @name chain * @memberOf _ * @category Chain * @returns {*} Returns the wrapper object. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // without explicit chaining * _(users).first(); * // => { 'user': 'barney', 'age': 36 } * * // with explicit chaining * _(users).chain() * .first() * .pick('age') * .value(); * // => { 'age': 36 } */ function wrapperChain() { return chain(this); } /** * Produces the result of coercing the unwrapped value to a string. * * @name toString * @memberOf _ * @category Chain * @returns {string} Returns the coerced string value. * @example * * _([1, 2, 3]).toString(); * // => '1,2,3' */ function wrapperToString() { return String(this.value()); } /** * Extracts the unwrapped value from its wrapper. * * @name valueOf * @memberOf _ * @alias toJSON, value * @category Chain * @returns {*} Returns the unwrapped value. * @example * * _([1, 2, 3]).valueOf(); * // => [1, 2, 3] */ function wrapperValueOf() { var index = -1, queue = this.__queue__, length = queue.length, result = this.__wrapped__; while (++index < length) { var args = [result], data = queue[index], object = data[1]; push.apply(args, data[2]); result = object[data[0]].apply(object, args); } return result; } /*------------------------------------------------------------------------*/ /** * Creates an array of elements corresponding to the specified keys, or indexes, * of the collection. Keys may be specified as individual arguments or as arrays * of keys. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {...(number|number[]|string|string[])} [props] The property names * or indexes of elements to pick, specified individually or in arrays. * @returns {Array} Returns the new array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); * // => ['a', 'c', 'e'] * * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ function at(collection) { var length = collection ? collection.length : 0; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { collection = toIterable(collection); } return baseAt(collection, baseFlatten(arguments, false, false, 1)); } /** * Checks if `value` is present in `collection` using `SameValueZero` for * equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of the collection. * * **Note:** `SameValueZero` is like strict equality, e.g. `===`, except that * `NaN` matches `NaN`. See the [ES6 spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @alias include * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {*} target The value to check for. * @param {number} [fromIndex=0] The index to search from. * @returns {boolean} Returns `true` if a matching element is found, else `false`. * @example * * _.contains([1, 2, 3], 1); * // => true * * _.contains([1, 2, 3], 1, 2); * // => false * * _.contains({ 'user': 'fred', 'age': 40 }, 'fred'); * // => true * * _.contains('pebbles', 'eb'); * // => true */ function contains(collection, target, fromIndex) { var length = collection ? collection.length : 0; if (!(typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER)) { collection = values(collection); length = collection.length; } if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } else { fromIndex = 0; } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) : (getIndexOf(collection, target, fromIndex) > -1); } /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the number of times the key was returned by `iteratee`. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); }); /** * Checks if the predicate returns truthy for **all** elements of `collection`. * The predicate is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements passed the predicate check, * else `false`. * @example * * _.every([true, 1, null, 'yes']); * // => false * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // using "_.pluck" callback shorthand * _.every(users, 'age'); * // => true * * // using "_.where" callback shorthand * _.every(users, { 'age': 36 }); * // => false */ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } return func(collection, predicate); } /** * Iterates over elements of `collection`, returning an array of all elements * the predicate returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias select * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [2, 4] * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40, 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.filter(users, 'blocked'); * // => [{ 'user': 'fred', 'age': 40, 'blocked': true }] * * // using "_.where" callback shorthand * _.filter(users, { 'age': 36 }); * // => [{ 'user': 'barney', 'age': 36 }] */ function filter(collection, predicate, thisArg) { var func = isArray(collection) ? arrayFilter : baseFilter; predicate = getCallback(predicate, thisArg, 3); return func(collection, predicate); } /** * Iterates over elements of `collection`, returning the first element that * the predicate returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40, 'blocked': true }, * { 'user': 'pebbles', 'age': 1 } * ]; * * _.find(users, function(chr) { * return chr.age < 40; * }); * // => { 'user': 'barney', 'age': 36 } * * // using "_.where" callback shorthand * _.find(users, { 'age': 1 }); * // => { 'user': 'pebbles', 'age': 1 } * * // using "_.pluck" callback shorthand * _.find(users, 'blocked'); * // => { 'user': 'fred', 'age': 40, 'blocked': true } */ function find(collection, predicate, thisArg) { if (isArray(collection)) { var index = findIndex(collection, predicate, thisArg); return index > -1 ? collection[index] : undefined; } predicate = getCallback(predicate, thisArg, 3); return baseFind(collection, predicate, baseEach); } /** * This method is like `_.find` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * * _.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1; }); * // => 3 */ function findLast(collection, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); return baseFind(collection, predicate, baseEachRight); } /** * Performs a deep comparison between each element in `collection` and the * source object, returning the first element that has equivalent property * values. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Object} source The object of property values to match. * @returns {*} Returns the matched element, else `undefined`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'employer': 'slate' }, * { 'user': 'fred', 'age': 40, 'employer': 'slate' } * ]; * * _.findWhere(users, { 'employer': 'slate' }); * // => { 'user': 'barney', 'age': 36, 'employer': 'slate' } * * _.findWhere(users, { 'age': 40 }); * // => { 'user': 'fred', 'age': 40, 'employer': 'slate' } */ function findWhere(collection, source) { return find(collection, matches(source)); } /** * Iterates over elements of `collection` invoking `iteratee` for each element. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * * @static * @memberOf _ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEach(function(n) { console.log(n); }); * // => logs each value and returns the array * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); * // => logs each value-key pair and returns the object (iteration order is not guaranteed) */ function forEach(collection, iteratee, thisArg) { return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) ? arrayEach(collection, iteratee) : baseEach(collection, baseCallback(iteratee, thisArg, 3)); } /** * This method is like `_.forEach` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each value from right to left and returns the array */ function forEachRight(collection, iteratee, thisArg) { return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) ? arrayEachRight(collection, iteratee) : baseEachRight(collection, baseCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding * value of each key is an array of the elements responsible for generating * the key. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using "_.pluck" callback shorthand * _.groupBy(['one', 'two', 'three'], 'length'); * // => { '3': ['one', 'two'], '5': ['three'] } */ var groupBy = createAggregator(function(result, value, key) { if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { result[key] = [value]; } }); /** * Creates an object composed of keys generated from the results of running * each element of the collection through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * * var keyData = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * * _.indexBy(keyData, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } * * _.indexBy(keyData, function(object) { return String.fromCharCode(object.code); }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * * _.indexBy(keyData, function(object) { return this.fromCharCode(object.code); }, String); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } */ var indexBy = createAggregator(function(result, value, key) { result[key] = value; }); /** * Invokes the method named by `methodName` on each element in the collection, * returning an array of the results of each invoked method. Any additional * arguments are provided to each invoked method. If `methodName` is a function * it is invoked for, and `this` bound to, each element in the collection. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {...*} [args] The arguments to invoke the method with. * @returns {Array} Returns the array of results. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ function invoke(collection, methodName) { return baseInvoke(collection, methodName, slice(arguments, 2)); } /** * Creates an array of values by running each element in the collection through * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); * // => [3, 6, 9] (iteration order is not guaranteed) * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // using "_.pluck" callback shorthand * _.map(users, 'user'); * // => ['barney', 'fred'] */ function map(collection, iteratee, thisArg) { iteratee = getCallback(iteratee, thisArg, 3); var func = isArray(collection) ? arrayMap : baseMap; return func(collection, iteratee); } /** * Retrieves the maximum value of `collection`. If the collection is empty * or falsey `-Infinity` is returned. If an iteratee function is provided it * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * * _.max([4, 2, 8, 6]); * // => 8 * * _.max([]); * // => -Infinity * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * _.max(users, function(chr) { return chr.age; }); * // => { 'user': 'fred', 'age': 40 }; * * // using "_.pluck" callback shorthand * _.max(users, 'age'); * // => { 'user': 'fred', 'age': 40 }; */ function max(collection, iteratee, thisArg) { var computed = -Infinity, result = computed, type = typeof iteratee; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { iteratee = null; } var noIteratee = iteratee == null, isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; while (++index < length) { var value = iterable[index]; if (value > result) { result = value; } } } else { iteratee = (noIteratee && isStr) ? charAtCallback : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { var current = iteratee(value, index, collection); if (current > computed || (current === -Infinity && current === result)) { computed = current; result = value; } }); } return result; } /** * Retrieves the minimum value of `collection`. If the collection is empty * or falsey `Infinity` is returned. If an iteratee function is provided it * is invoked for each value in the collection to generate the criterion by * which the value is ranked. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.pluck" * or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * * _.min([4, 2, 8, 6]); * // => 2 * * _.min([]); * // => Infinity * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * _.min(users, function(chr) { return chr.age; }); * // => { 'user': 'barney', 'age': 36 }; * * // using "_.pluck" callback shorthand * _.min(users, 'age'); * // => { 'user': 'barney', 'age': 36 }; */ function min(collection, iteratee, thisArg) { var computed = Infinity, result = computed, type = typeof iteratee; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[iteratee] === collection) { iteratee = null; } var noIteratee = iteratee == null, isArr = noIteratee && isArray(collection), isStr = !isArr && isString(collection); if (noIteratee && !isStr) { var index = -1, iterable = toIterable(collection), length = iterable.length; while (++index < length) { var value = iterable[index]; if (value < result) { result = value; } } } else { iteratee = (noIteratee && isStr) ? charAtCallback : getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, index, collection) { var current = iteratee(value, index, collection); if (current < computed || (current === Infinity && current === result)) { computed = current; result = value; } }); } return result; } /** * Creates an array of elements split into two groups, the first of which * contains elements the predicate returns truthy for, while the second of which * contains elements the predicate returns falsey for. The predicate is bound * to `thisArg` and invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the array of grouped elements. * @example * * _.partition([1, 2, 3], function(n) { return n % 2; }); * // => [[1, 3], [2]] * * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); * // => [[1, 3], [2]] * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40, 'blocked': true }, * { 'user': 'pebbles', 'age': 1 } * ]; * * // using "_.where" callback shorthand * _.map(_.partition(users, { 'age': 1 }), function(array) { return _.pluck(array, 'user'); }); * // => [['pebbles'], ['barney', 'fred']] * * // using "_.pluck" callback shorthand * _.map(_.partition(users, 'blocked'), function(array) { return _.pluck(array, 'user'); }); * // => [['fred'], ['barney', 'pebbles']] */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); }, function() { return [[], []]; }); /** * Retrieves the value of a specified property from all elements in the collection. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {string} key The name of the property to pluck. * @returns {Array} Returns the property values. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * _.pluck(users, 'user'); * // => ['barney', 'fred'] * * var userIndex = _.indexBy(users, 'user'); * _.pluck(userIndex, 'age'); * // => [36, 40] (iteration order is not guaranteed) */ function pluck(collection, key) { return map(collection, property(key)); } /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of the collection is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * * @static * @memberOf _ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } (iteration order is not guaranteed) */ function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** * This method is like `_.reduce` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * var array = [[0, 1], [2, 3], [4, 5]]; * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ function reduceRight(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduceRight : baseReduce; return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** * The opposite of `_.filter`; this method returns the elements of `collection` * the predicate does **not** return truthy for. * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [1, 3] * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40, 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.reject(users, 'blocked'); * // => [{ 'user': 'barney', 'age': 36 }] * * // using "_.where" callback shorthand * _.reject(users, { 'age': 36 }); * // => [{ 'user': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { var func = isArray(collection) ? arrayFilter : baseFilter; predicate = getCallback(predicate, thisArg, 3); return func(collection, function(value, index, collection) { return !predicate(value, index, collection); }); } /** * Retrieves a random element or `n` random elements from a collection. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to sample. * @param {number} [n] The number of elements to sample. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {*} Returns the random sample(s). * @example * * _.sample([1, 2, 3, 4]); * // => 2 * * _.sample([1, 2, 3, 4], 2); * // => [3, 1] */ function sample(collection, n, guard) { if (n == null || guard) { collection = toIterable(collection); var length = collection.length; return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; } var result = shuffle(collection); result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length); return result; } /** * Creates an array of shuffled values, using a version of the Fisher-Yates * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) * for more details. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to shuffle. * @returns {Array} Returns the new shuffled array. * @example * * _.shuffle([1, 2, 3, 4]); * // => [4, 1, 3, 2] */ function shuffle(collection) { collection = toIterable(collection); var index = -1, length = collection.length, result = Array(length); while (++index < length) { var rand = baseRandom(0, index); if (index != rand) { result[index] = result[rand]; } result[rand] = collection[index]; } return result; } /** * Gets the size of the collection by returning `collection.length` for * array-like values or the number of own enumerable properties for objects. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns `collection.length` or number of own enumerable properties. * @example * * _.size([1, 2]); * // => 2 * * _.size({ 'one': 1, 'two': 2, 'three': 3 }); * // => 3 * * _.size('pebbles'); * // => 7 */ function size(collection) { var length = collection ? collection.length : 0; return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) ? length : keys(collection).length; } /** * Checks if the predicate returns truthy for **any** element of `collection`. * The function returns as soon as it finds a passing value and does not iterate * over the entire collection. The predicate is bound to `thisArg` and invoked * with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias any * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. * @example * * _.some([null, 0, 'yes', false], Boolean); * // => true * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40, 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.some(users, 'blocked'); * // => true * * // using "_.where" callback shorthand * _.some(users, { 'age': 1 }); * // => false */ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } return func(collection, predicate); } /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an array of property names is provided for `iteratee` the collection * is sorted by each property value. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=identity] The function * invoked per iteration. If property name(s) or an object is provided it * is used to create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. * @example * * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'barney', 'age': 26 }, * { 'user': 'fred', 'age': 30 } * ]; * * // using "_.pluck" callback shorthand * _.map(_.sortBy(users, 'age'), _.values); * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]] * * // sorting by multiple properties * _.map(_.sortBy(users, ['user', 'age']), _.values); * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ function sortBy(collection, iteratee, thisArg) { var index = -1, length = collection ? collection.length : 0, multi = iteratee && isArray(iteratee), result = []; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { result.length = length; } if (!multi) { iteratee = getCallback(iteratee, thisArg, 3); } baseEach(collection, function(value, key, collection) { if (multi) { var length = iteratee.length, criteria = Array(length); while (length--) { criteria[length] = value == null ? undefined : value[iteratee[length]]; } } else { criteria = iteratee(value, key, collection); } result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; }); length = result.length; result.sort(multi ? compareMultipleAscending : compareAscending); while (length--) { result[length] = result[length].value; } return result; } /** * Converts `collection` to an array. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to convert. * @returns {Array} Returns the new converted array. * @example * * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); * // => [2, 3, 4] */ function toArray(collection) { var length = collection ? collection.length : 0; if (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) { return (support.unindexedChars && isString(collection)) ? collection.split('') : baseSlice(collection); } return values(collection); } /** * Performs a deep comparison between each element in `collection` and the * source object, returning an array of all elements that have equivalent * property values. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Object} source The object of property values to match. * @returns {Array} Returns the new filtered array. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'employer': 'slate', 'pets': ['hoppy'] }, * { 'user': 'fred', 'age': 40, 'employer': 'slate', 'pets': ['baby puss', 'dino'] } * ]; * * _.pluck(_.where(users, { 'age': 36 }), 'user'); * // => ['barney'] * * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user'); * // => ['fred'] * * _.pluck(_.where(users, { 'employer': 'slate' }), 'user'); * // => ['barney', 'fred'] */ function where(collection, source) { return filter(collection, matches(source)); } /*------------------------------------------------------------------------*/ /** * The opposite of `_.before`; this method creates a function that invokes * `func` only after it is called `n` times. * * @static * @memberOf _ * @category Function * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var saves = ['profile', 'settings']; * * var done = _.after(saves.length, function() { * console.log('done saving!'); * }); * * _.forEach(saves, function(type) { * asyncSave({ 'type': type, 'complete': done }); * }); * // => logs 'done saving!' after all saves have completed */ function after(n, func) { if (!isFunction(func)) { if (isFunction(n)) { var temp = n; n = func; func = temp; } else { throw new TypeError(FUNC_ERROR_TEXT); } } n = nativeIsFinite(n = +n) ? n : 0; return function() { if (--n < 1) { return func.apply(this, arguments); } }; } /** * Creates a function that invokes `func`, with the `this` binding and * arguments of the created function, until it is called `n` times. * * @static * @memberOf _ * @category Function * @param {number} n The number of times `func` may be called. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * jQuery('#add').on('click', _.before(5, addContactToList)); * // => allows adding up to 5 contacts to the list */ function before(n, func) { var result; if (!isFunction(func)) { if (isFunction(n)) { var temp = n; n = func; func = temp; } else { throw new TypeError(FUNC_ERROR_TEXT); } } return function() { if (--n > 0) { result = func.apply(this, arguments); } else { func = null; } return result; }; } /** * Creates a function that invokes `func` with the `this` binding of `thisArg` * and prepends any additional `bind` arguments to those provided to the bound * function. * * **Note:** Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to bind. * @param {*} [thisArg] The `this` binding of `func`. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var func = function(greeting) { * return greeting + ' ' + this.user; * }; * * func = _.bind(func, { 'user': 'fred' }, 'hi'); * func(); * // => 'hi fred' */ function bind(func, thisArg) { if (arguments.length < 3) { return createWrapper(func, BIND_FLAG, null, thisArg); } var args = slice(arguments, 2), holders = replaceHolders(args, bind.placeholder); return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, holders, thisArg); } /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays * of method names. If no method names are provided all enumerable function * properties, own and inherited, of `object` are bound. * * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ * @category Function * @param {Object} object The object to bind and assign the bound methods to. * @param {...(string|string[])} [methodNames] The object method names to bind, * specified as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * * var view = { * 'label': 'docs', * 'onClick': function() { console.log('clicked ' + this.label); } * }; * * _.bindAll(view); * jQuery('#docs').on('click', view.onClick); * // => logs 'clicked docs' when the element is clicked */ function bindAll(object) { return baseBindAll(object, arguments.length > 1 ? baseFlatten(arguments, false, false, 1) : functions(object) ); } /** * Creates a function that invokes the method at `object[key]` and prepends * any additional `bindKey` arguments to those provided to the bound function. * This method differs from `_.bind` by allowing bound functions to reference * methods that may be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * * @static * @memberOf _ * @category Function * @param {Object} object The object the method belongs to. * @param {string} key The key of the method. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var object = { * 'user': 'fred', * 'greet': function(greeting) { * return greeting + ' ' + this.user; * } * }; * * var func = _.bindKey(object, 'greet', 'hi'); * func(); * // => 'hi fred' * * object.greet = function(greeting) { * return greeting + 'ya ' + this.user + '!'; * }; * * func(); * // => 'hiya fred!' */ function bindKey(object, key) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (arguments.length > 2) { var args = slice(arguments, 2), holders = replaceHolders(args, bindKey.placeholder); } return args ? createWrapper(key, bitmask, null, object, args, holders) : createWrapper(key, bitmask, null, object); } /** * Creates a function that accepts one or more arguments of `func` that when * called either invokes `func` returning its result if all `func` arguments * have been provided, or returns a function that accepts one or more of the * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. * * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @returns {Function} Returns the new curried function. * @example * * var curried = _.curry(function(a, b, c) { * console.log([a, b, c]); * }); * * curried(1)(2)(3); * // => [1, 2, 3] * * curried(1, 2)(3); * // => [1, 2, 3] * * curried(1, 2, 3); * // => [1, 2, 3] */ function curry(func, arity) { var result = baseCurry(func, CURRY_FLAG, arity); result.placeholder = curry.placeholder; return result; } /** * This method is like `_.curry` except that arguments are applied to `func` * in the manner of `_.partialRight` instead of `_.partial`. * * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @returns {Function} Returns the new curried function. * @example * * var curried = _.curryRight(function(a, b, c) { * console.log([a, b, c]); * }); * * curried(3)(2)(1); * // => [1, 2, 3] * * curried(2, 3)(1); * // => [1, 2, 3] * * curried(1, 2, 3); * // => [1, 2, 3] */ function curryRight(func, arity) { var result = baseCurry(func, CURRY_RIGHT_FLAG, arity); result.placeholder = curryRight.placeholder; return result; } /** * Creates a function that delays the invocation of `func` until after `wait` * milliseconds have elapsed since the last time it was invoked. The created * function comes with a `cancel` method to cancel delayed invokes. Provide an * options object to indicate that `func` should be invoked on the leading * and/or trailing edge of the `wait` timeout. Subsequent calls to the * debounced function return the result of the last `func` invocation. * * **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 * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ * @category Function * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be * delayed before it is invoked. * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * }); * * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * }, false); * * // cancel a debounced call * var todoChanges = _.debounce(batchLog, 1000); * Object.observe(models.todo, todoChanges); * * Object.observe(models, function(changes) { * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { * todoChanges.cancel(); * } * }, ['delete']); * * // ...at some point `models.todo` is changed * models.todo.completed = true; * * // ...before 1 second has passed `models.todo` is deleted * // which cancels the debounced `todoChanges` call * delete models.todo; */ function debounce(func, wait, options) { var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } wait = wait < 0 ? 0 : wait; if (options === true) { var leading = true; trailing = false; } else if (isObject(options)) { leading = options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? options.trailing : trailing; } function cancel() { if (timeoutId) { clearTimeout(timeoutId); } if (maxTimeoutId) { clearTimeout(maxTimeoutId); } maxTimeoutId = timeoutId = trailingCall = undefined; } function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { if (maxTimeoutId) { clearTimeout(maxTimeoutId); } var isCalled = trailingCall; maxTimeoutId = timeoutId = trailingCall = undefined; if (isCalled) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = null; } } } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { if (timeoutId) { clearTimeout(timeoutId); } maxTimeoutId = timeoutId = trailingCall = undefined; if (trailing || (maxWait !== wait)) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = null; } } } function debounced() { args = arguments; stamp = now(); thisArg = this; trailingCall = trailing && (timeoutId || !leading); if (maxWait === false) { var leadingCall = leading && !timeoutId; } else { if (!maxTimeoutId && !leading) { lastCalled = stamp; } var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; if (isCalled) { if (maxTimeoutId) { maxTimeoutId = clearTimeout(maxTimeoutId); } lastCalled = stamp; result = func.apply(thisArg, args); } else if (!maxTimeoutId) { maxTimeoutId = setTimeout(maxDelayed, remaining); } } if (isCalled && timeoutId) { timeoutId = clearTimeout(timeoutId); } else if (!timeoutId && wait !== maxWait) { timeoutId = setTimeout(delayed, wait); } if (leadingCall) { isCalled = true; result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { args = thisArg = null; } return result; } debounced.cancel = cancel; return debounced; } /** * Defers invoking the `func` until the current call stack has cleared. Any * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to defer. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.defer(function(text) { console.log(text); }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ function defer(func) { if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } var args = slice(arguments, 1); return setTimeout(function() { func.apply(undefined, args); }, 1); } /** * Invokes `func` after `wait` milliseconds. Any additional arguments are * provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.delay(function(text) { console.log(text); }, 1000, 'later'); * // => logs 'later' after one second */ function delay(func, wait) { if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } var args = slice(arguments, 2); return setTimeout(function() { func.apply(undefined, args); }, wait); } /** * Creates a function that invokes the provided functions with the `this` * binding of the created function, where each successive invocation is * supplied the return value of the previous. * * @static * @memberOf _ * @category Function * @param {...Function} [funcs] Functions to invoke. * @returns {Function} Returns the new function. * @example * * function add(x, y) { * return x + y; * } * * function square(n) { * return n * n; * } * * var addSquare = _.flow(add, square); * addSquare(1, 2); * // => 9 */ function flow() { var funcs = arguments, length = funcs.length; if (!length) { return function() {}; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); } return function() { var index = 0, result = funcs[index].apply(this, arguments); while (++index < length) { result = funcs[index].call(this, result); } return result; }; } /** * This method is like `_.flow` except that it creates a function that * invokes the provided functions from right to left. * * @static * @memberOf _ * @alias backflow, compose * @category Function * @param {...Function} [funcs] Functions to invoke. * @returns {Function} Returns the new function. * @example * * function add(x, y) { * return x + y; * } * * function square(n) { * return n * n; * } * * var addSquare = _.flowRight(square, add); * addSquare(1, 2); * // => 9 */ function flowRight() { var funcs = arguments, fromIndex = funcs.length - 1; if (fromIndex < 0) { return function() {}; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); } return function() { var index = fromIndex, result = funcs[index].apply(this, arguments); while (index--) { result = funcs[index].call(this, result); } return result; }; } /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the cache key. The `func` is * invoked with the `this` binding of the memoized function. The result cache * is exposed as the `cache` property on the memoized function. * * @static * @memberOf _ * @category Function * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] The function to resolve the cache key. * @returns {Function} Returns the new memoizing function. * @example * * var fibonacci = _.memoize(function(n) { * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); * }); * * fibonacci(9) * // => 34 * * // modifying the result cache * var upperCase = _.memoize(function(string) { * return string.toUpperCase(); * }); * * upperCase('fred'); * // => 'FRED' * * upperCase.cache.fred = 'BARNEY' * upperCase('fred'); * // => 'BARNEY' */ function memoize(func, resolver) { if (!isFunction(func) || (resolver && !isFunction(resolver))) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { var key = resolver ? resolver.apply(this, arguments) : arguments[0]; if (key == '__proto__') { return func.apply(this, arguments); } var cache = memoized.cache; return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); }; memoized.cache = {}; return memoized; } /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the * created function. * * @static * @memberOf _ * @category Function * @param {Function} predicate The predicate to negate. * @returns {Function} Returns the new function. * @example * * function isEven(n) { * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); * // => [1, 3, 5] */ function negate(predicate) { if (!isFunction(predicate)) { throw new TypeError(FUNC_ERROR_TEXT); } return function() { return !predicate.apply(this, arguments); }; } /** * Creates a function that is restricted to invoking `func` once. Repeat calls * to the function return the value of the first call. The `func` is invoked * with the `this` binding of the created function. * * @static * @memberOf _ * @type Function * @category Function * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var initialize = _.once(createApplication); * initialize(); * initialize(); * // `initialize` invokes `createApplication` once */ var once = partial(before, 2); /** * Creates a function that invokes `func` with `partial` arguments prepended * to those provided to the new function. This method is similar to `_.bind` * except it does **not** alter the `this` binding. * * **Note:** This method does not set the `length` property of partially * applied functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; * var sayHelloTo = _.partial(greet, 'hello'); * sayHelloTo('fred'); * // => 'hello fred' */ function partial(func) { var args = slice(arguments, 1), holders = replaceHolders(args, partial.placeholder); return basePartial(func, PARTIAL_FLAG, args, holders); } /** * This method is like `_.partial` except that partially applied arguments * are appended to those provided to the new function. * * **Note:** This method does not set the `length` property of partially applied * functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; * var greetFred = _.partialRight(greet, 'fred'); * greetFred('hello'); * // => 'hello fred' * * // create a deep `_.defaults` * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) { * return _.merge(value, other, deep); * }); * * var object = { 'a': { 'b': { 'c': 1 } } }, * source = { 'a': { 'b': { 'c': 2, 'd': 2 } } }; * * defaultsDeep(object, source); * // => { 'a': { 'b': { 'c': 1, 'd': 2 } } } */ function partialRight(func) { var args = slice(arguments, 1), holders = replaceHolders(args, partialRight.placeholder); return basePartial(func, PARTIAL_RIGHT_FLAG, args, holders); } /** * Creates a function that only invokes `func` at most once per every `wait` * milliseconds. The created function comes with a `cancel` method to cancel * delayed invokes. Provide an options object to indicate that `func` should * be invoked on the leading and/or trailing edge of the `wait` timeout. * Subsequent calls to the throttled function return the result of the last * `func` call. * * **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 * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) * for details over the differences between `_.throttle` and `_.debounce`. * * @static * @memberOf _ * @category Function * @param {Function} func The function to throttle. * @param {number} wait The number of milliseconds to throttle invocations to. * @param {Object} [options] The options object. * @param {boolean} [options.leading=true] Specify invoking on the leading * edge of the timeout. * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * * // 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 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) * jQuery('.interactive').on('click', throttled); * * // cancel a trailing throttled call * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { var leading = true, trailing = true; if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } if (options === false) { leading = false; } else if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } debounceOptions.leading = leading; debounceOptions.maxWait = +wait; debounceOptions.trailing = trailing; return debounce(func, wait, debounceOptions); } /** * Creates a function that provides `value` to the wrapper function as its * first argument. Any additional arguments provided to the function are * appended to those provided to the wrapper function. The wrapper is invoked * with the `this` binding of the created function. * * @static * @memberOf _ * @category Function * @param {*} value The value to wrap. * @param {Function} wrapper The wrapper function. * @returns {Function} Returns the new function. * @example * * var p = _.wrap(_.escape, function(func, text) { * return '

' + func(text) + '

'; * }); * * p('fred, barney, & pebbles'); * // => '

fred, barney, & pebbles

' */ function wrap(value, wrapper) { return basePartial(wrapper, PARTIAL_FLAG, [value], []); } /*------------------------------------------------------------------------*/ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value, index|key). * * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to clone. * @param {boolean} [isDeep=false] Specify a deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {*} Returns the cloned value. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * var shallow = _.clone(users); * shallow[0] === users[0]; * // => true * * var deep = _.clone(users, true); * deep[0] === users[0]; * // => false * * _.mixin({ * 'clone': _.partialRight(_.clone, function(value) { * return _.isElement(value) ? value.cloneNode(false) : undefined; * }) * }); * * var clone = _.clone(document.body); * clone.childNodes.length; * // => 0 */ function clone(value, isDeep, customizer, thisArg) { var type = typeof isDeep; // juggle arguments if (type != 'boolean' && isDeep != null) { thisArg = customizer; customizer = isDeep; isDeep = false; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[customizer] === value) { customizer = null; } } customizer = typeof customizer == 'function' && baseCallback(customizer, thisArg, 1); return baseClone(value, isDeep, customizer); } /** * Creates a deep clone of `value`. If `customizer` is provided it is invoked * to produce the cloned values. If `customizer` returns `undefined` cloning * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value, index|key). * * **Note:** This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {*} Returns the deep cloned value. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * var deep = _.cloneDeep(users); * deep[0] === users[0]; * // => false * * var view = { * 'label': 'docs', * 'node': element * }; * * var clone = _.cloneDeep(view, function(value) { * return _.isElement(value) ? value.cloneNode(true) : undefined; * }); * * clone.node == view.node; * // => false */ function cloneDeep(value, customizer, thisArg) { customizer = typeof customizer == 'function' && baseCallback(customizer, thisArg, 1); return baseClone(value, true, customizer); } /** * Checks if `value` is classified as an `arguments` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an `arguments` object, else `false`. * @example * * (function() { return _.isArguments(arguments); })(); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { var length = (value && typeof value == 'object') ? value.length : undefined; return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER && toString.call(value) == argsClass) || false; } // fallback for environments without a `[[Class]]` for `arguments` objects if (!support.argsClass) { isArguments = function(value) { var length = (value && typeof value == 'object') ? value.length : undefined; return (typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee')) || false; }; } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * (function() { return _.isArray(arguments); })(); * // => false */ var isArray = nativeIsArray || function(value) { return (value && typeof value == 'object' && typeof value.length == 'number' && toString.call(value) == arrayClass) || false; }; /** * Checks if `value` is classified as a boolean primitive or object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isBoolean(false); * // => true * * _.isBoolean(null); * // => false */ function isBoolean(value) { return (value === true || value === false || value && typeof value == 'object' && toString.call(value) == boolClass) || false; } /** * Checks if `value` is classified as a `Date` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isDate(new Date); * // => true * * _.isDate('Mon April 23 2012'); * // => false */ function isDate(value) { return (value && typeof value == 'object' && toString.call(value) == dateClass) || false; } /** * Checks if `value` is a DOM element. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true * * _.isElement(''); * // => false */ function isElement(value) { return (value && typeof value == 'object' && value.nodeType === 1 && (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isHostObject(value))) || false; } // fallback for environments without DOM support if (!support.dom) { isElement = function(value) { return (value && typeof value == 'object' && value.nodeType === 1 && !isPlainObject(value)) || false; }; } /** * Checks if a collection is empty. A value is considered empty unless it is * an array-like value with a length greater than `0` or an object with own * enumerable properties. * * @static * @memberOf _ * @category Lang * @param {Array|Object|string} value The value to inspect. * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * * _.isEmpty(null); * // => true * * _.isEmpty(true); * // => true * * _.isEmpty(1); * // => true * * _.isEmpty([1, 2, 3]); * // => false * * _.isEmpty({ 'a': 1 }); * // => false */ function isEmpty(value) { if (value == null) { return true; } var length = value.length; if ((typeof length == 'number' && length > -1 && length <= MAX_SAFE_INTEGER) && (isArray(value) || isString(value) || isArguments(value) || (typeof value == 'object' && isFunction(value.splice)))) { return !length; } return !keys(value).length; } /** * Performs a deep comparison between two values to determine if they are * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other, key). * * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. * * @static * @memberOf _ * @category Lang * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @param {Function} [customizer] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'user': 'fred' }; * var other = { 'user': 'fred' }; * * object == other; * // => false * * _.isEqual(object, other); * // => true * * var words = ['hello', 'goodbye']; * var otherWords = ['hi', 'goodbye']; * * _.isEqual(words, otherWords, function() { * return _.every(arguments, _.bind(RegExp.prototype.test, /^h(?:i|ello)$/)) || undefined; * }); * // => true */ function isEqual(value, other, customizer, thisArg) { customizer = typeof customizer == 'function' && baseCallback(customizer, thisArg, 3); return (!customizer && isStrictComparable(value) && isStrictComparable(other)) ? value === other : baseIsEqual(value, other, customizer); } /** * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, * `SyntaxError`, `TypeError`, or `URIError` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an error object, else `false`. * @example * * _.isError(new Error); * // => true * * _.isError(Error); * // => false */ function isError(value) { return (value && typeof value == 'object' && toString.call(value) == errorClass) || false; } /** * Checks if `value` is a finite primitive number. * * **Note:** This method is based on ES6 `Number.isFinite`. See the * [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * * _.isFinite(10); * // => true * * _.isFinite('10'); * // => false * * _.isFinite(true); * // => false * * _.isFinite(Object(10)); * // => false * * _.isFinite(Infinity); * // => false */ var isFinite = nativeNumIsFinite || function(value) { return typeof value == 'number' && nativeIsFinite(value); }; /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ function isFunction(value) { // avoid a Chakra bug in IE 11 // https://github.com/jashkenas/underscore/issues/1621 return typeof value == 'function' || false; } // fallback for older versions of Chrome and Safari if (isFunction(/x/)) { isFunction = function(value) { return typeof value == 'function' && toString.call(value) == funcClass; }; } /** * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * **Note:** See the [ES5 spec](http://es5.github.io/#x8) for more details. * * @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(1); * // => false */ function isObject(value) { // avoid a V8 bug in Chrome 19-20 // https://code.google.com/p/v8/issues/detail?id=2291 var type = typeof value; return type == 'function' || (value && type == 'object') || false; } /** * Checks if `value` is `NaN`. * * **Note:** This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * * _.isNaN(NaN); * // => true * * _.isNaN(new Number(NaN)); * // => true * * isNaN(undefined); * // => true * * _.isNaN(undefined); * // => false */ function isNaN(value) { // `NaN` as a primitive is the only value that is not equal to itself // (perform the `[[Class]]` check first to avoid errors with some host objects in IE) return isNumber(value) && value != +value; } /** * 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 (isFunction(value)) { return reNative.test(fnToString.call(value)); } return (value && typeof value == 'object' && (isHostObject(value) ? reNative : reHostCtor).test(value)) || false; } /** * Checks if `value` is `null`. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `null`, else `false`. * @example * * _.isNull(null); * // => true * * _.isNull(void 0); * // => false */ function isNull(value) { return value === null; } /** * Checks if `value` is classified as a `Number` primitive or object. * * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isNumber(8.4); * // => true * * _.isNumber(NaN); * // => true * * _.isNumber('8.4'); * // => false */ function isNumber(value) { var type = typeof value; return type == 'number' || (value && type == 'object' && toString.call(value) == numberClass) || false; } /** * Checks if `value` is an object created by the `Object` constructor or has * a `[[Prototype]]` of `null`. * * **Note:** This method assumes objects created by the `Object` constructor * have no inherited enumerable properties. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * _.isPlainObject(new Shape); * // => false * * _.isPlainObject([1, 2, 3]); * // => false * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true * * _.isPlainObject(Object.create(null)); * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { return false; } var valueOf = value.valueOf, objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); return objProto ? (value == objProto || getPrototypeOf(value) == objProto) : shimIsPlainObject(value); }; /** * Checks if `value` is classified as a `RegExp` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isRegExp(/abc/); * // => true * * _.isRegExp('/abc/'); * // => false */ function isRegExp(value) { return (isObject(value) && toString.call(value) == regexpClass) || false; } /** * 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' || (value && typeof value == 'object' && toString.call(value) == stringClass) || false; } /** * Checks if `value` is `undefined`. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true * * _.isUndefined(null); * // => false */ function isUndefined(value) { return typeof value == 'undefined'; } /*------------------------------------------------------------------------*/ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments; * (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ * @alias extend * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @param {Function} [customizer] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {Object} Returns the destination object. * @example * * _.assign({ 'user': 'fred' }, { 'age': 40 }, { 'employer': 'slate' }); * // => { 'user': 'fred', 'age': 40, 'employer': 'slate' } * * var defaults = _.partialRight(_.assign, function(value, other) { * return typeof value == 'undefined' ? other : value; * }); * * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred', 'employer': 'slate' }); * // => { 'user': 'barney', 'age': 36, 'employer': 'slate' } */ var assign = createAssigner(baseAssign); /** * Creates an object that inherits from the given `prototype` object. If a * `properties` object is provided its own enumerable properties are assigned * to the created object. * * @static * @memberOf _ * @category Object * @param {Object} prototype The object to inherit from. * @param {Object} [properties] The properties to assign to the object. * @returns {Object} Returns the new object. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * function Circle() { * Shape.call(this); * } * * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); * * var circle = new Circle; * circle instanceof Circle; * // => true * * circle instanceof Shape; * // => true */ function create(prototype, properties) { var result = baseCreate(prototype); return properties ? baseAssign(result, properties) : result; } /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property are ignored. * * **Note:** See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight) * for a deep version of this method. * * @static * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns the destination object. * @example * * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred', 'employer': 'slate' }); * // => { 'user': 'barney', 'age': 36, 'employer': 'slate' } */ function defaults(object) { if (object == null) { return object; } var args = baseSlice(arguments); args.push(assignDefaults); return assign.apply(undefined, args); } /** * This method is like `_.findIndex` except that it returns the key of the * first element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * * var users = { * 'barney': { 'age': 36 }, * 'fred': { 'age': 40, 'blocked': true }, * 'pebbles': { 'age': 1 } * }; * * _.findKey(users, function(chr) { * return chr.age < 40; * }); * // => 'barney' (iteration order is not guaranteed) * * // using "_.where" callback shorthand * _.findKey(users, { 'age': 1 }); * // => 'pebbles' * * // using "_.pluck" callback shorthand * _.findKey(users, 'blocked'); * // => 'fred' */ function findKey(object, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); return baseFind(object, predicate, baseForOwn, true); } /** * This method is like `_.findKey` except that it iterates over elements of * a collection in the opposite order. * * If a property name is provided for `predicate` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * * var users = { * 'barney': { 'age': 36, 'blocked': true }, * 'fred': { 'age': 40 }, * 'pebbles': { 'age': 1, 'blocked': true } * }; * * _.findLastKey(users, function(chr) { * return chr.age < 40; * }); * // => returns `pebbles`, assuming `_.findKey` returns `barney` * * // using "_.where" callback shorthand * _.findLastKey(users, { 'age': 40 }); * // => 'fred' * * // using "_.pluck" callback shorthand * _.findLastKey(users, 'blocked'); * // => 'pebbles' */ function findLastKey(object, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); return baseFind(object, predicate, baseForOwnRight, true); } /** * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * Shape.prototype.z = 0; * * _.forIn(new Shape, function(value, key) { * console.log(key); * }); * // => logs 'x', 'y', and 'z' (iteration order is not guaranteed) */ function forIn(object, iteratee, thisArg) { if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { iteratee = baseCallback(iteratee, thisArg, 3); } return baseFor(object, iteratee, keysIn); } /** * This method is like `_.forIn` except that it iterates over properties of * `object` in the opposite order. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * Shape.prototype.z = 0; * * _.forInRight(new Shape, function(value, key) { * console.log(key); * }); * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z' */ function forInRight(object, iteratee, thisArg) { iteratee = baseCallback(iteratee, thisArg, 3); return baseForRight(object, iteratee, keysIn); } /** * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs '0', '1', and 'length' (iteration order is not guaranteed) */ function forOwn(object, iteratee, thisArg) { if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { iteratee = baseCallback(iteratee, thisArg, 3); } return baseForOwn(object, iteratee); } /** * This method is like `_.forOwn` except that it iterates over properties of * `object` in the opposite order. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ function forOwnRight(object, iteratee, thisArg) { iteratee = baseCallback(iteratee, thisArg, 3); return baseForRight(object, iteratee, keys); } /** * Creates an array of function property names from all enumerable properties, * own and inherited, of `object`. * * @static * @memberOf _ * @alias methods * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the new array of property names. * @example * * _.functions(_); * // => ['all', 'any', 'bind', ...] */ function functions(object) { return baseFunctions(object, keysIn(object)); } /** * Checks if the specified property name exists as a direct property of `object`, * instead of an inherited property. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @param {string} key The name of the property to check. * @returns {boolean} Returns `true` if key is a direct property, else `false`. * @example * * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); * // => true */ function has(object, key) { return object ? hasOwnProperty.call(object, key) : false; } /** * Creates an object composed of the inverted keys and values of the given * object. If the given object contains duplicate values, subsequent values * overwrite property assignments of previous values unless `multiValue` * is `true`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to invert. * @param {boolean} [multiValue=false] Allow multiple values per key. * @returns {Object} Returns the new inverted object. * @example * * _.invert({ 'first': 'fred', 'second': 'barney' }); * // => { 'fred': 'first', 'barney': 'second' } * * // without `multiValue` * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }); * // => { 'fred': 'third', 'barney': 'second' } * * // with `multiValue` * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); * // => { 'fred': ['first', 'third'], 'barney': ['second'] } */ function invert(object, multiValue) { var index = -1, props = keys(object), length = props.length, result = {}; while (++index < length) { var key = props[index], value = object[key]; if (multiValue) { if (hasOwnProperty.call(result, value)) { result[value].push(key); } else { result[value] = [key]; } } else { result[value] = key; } } return result; } /** * Creates an array of the own enumerable property names of `object`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property names. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * Shape.prototype.z = 0; * * _.keys(new Shape); * // => ['x', 'y'] (iteration order is not guaranteed) */ var keys = !nativeKeys ? shimKeys : function(object) { object = toObject(object); var Ctor = object.constructor, length = object.length; if ((Ctor && Ctor.prototype === object) || (typeof length == 'number' && length > 0) || (support.enumPrototypes && typeof object == 'function')) { return shimKeys(object); } return nativeKeys(object); }; /** * Creates an array of the own and inherited enumerable property names of `object`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property names. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * Shape.prototype.z = 0; * * _.keysIn(new Shape); * // => ['x', 'y', 'z'] (iteration order is not guaranteed) */ function keysIn(object) { if (object == null) { return []; } object = toObject(object); var length = object.length; length = (typeof length == 'number' && length > 0 && (isArray(object) || (support.nonEnumStrings && isString(object)) || (support.nonEnumArgs && isArguments(object))) && length) || 0; var keyIndex, Ctor = object.constructor, index = -1, isProto = Ctor && Ctor.prototype === object, maxIndex = length - 1, result = Array(length), skipIndexes = length > 0, skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), skipProto = support.enumPrototypes && typeof object == 'function'; while (++index < length) { result[index] = String(index); } // Lo-Dash skips the `constructor` property when it infers it is iterating // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` // attribute of an existing property and the `constructor` property of a // prototype defaults to non-enumerable. for (var key in object) { if (!(isProto && key == 'constructor') && !(skipProto && key == 'prototype') && !(skipErrorProps && (key == 'message' || key == 'name')) && !(skipIndexes && (keyIndex = +key, keyIndex > -1 && keyIndex <= maxIndex && keyIndex % 1 == 0))) { result.push(key); } } if (support.nonEnumShadows && object !== objectProto) { index = -1; length = shadowedProps.length; if (isProto) { var className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object), nonEnum = nonEnumProps[className]; } while (++index < length) { key = shadowedProps[index]; if (!(nonEnum && nonEnum[key]) && hasOwnProperty.call(object, key)) { result.push(key); } } } return result; } /** * Creates an object with the same keys as `object` and values generated by * running each own enumerable property of `object` through `iteratee`. The * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * If a property name is provided for `iteratee` the created "_.pluck" style * callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.where" style callback * returns `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function|Object|string} [iteratee=identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.pluck" or "_.where" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the new mapped object. * @example * * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(n) { return n * 3; }); * // => { 'a': 3, 'b': 6, 'c': 9 } * * var users = { * 'fred': { 'user': 'fred', 'age': 40 }, * 'pebbles': { 'user': 'pebbles', 'age': 1 } * }; * * // using "_.pluck" callback shorthand * _.mapValues(users, 'age'); * // => { 'fred': 40, 'pebbles': 1 } */ function mapValues(object, iteratee, thisArg) { iteratee = getCallback(iteratee, thisArg, 3); var result = {} baseForOwn(object, function(value, key, object) { result[key] = iteratee(value, key, object); }); return result; } /** * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * overwrite property assignments of previous sources. If `customizer` is * provided it is invoked to produce the merged values of the destination and * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked * with five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @param {Function} [customizer] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {Object} Returns the destination object. * @example * * var users = { * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] * }; * * var ages = { * 'data': [{ 'age': 36 }, { 'age': 40 }] * }; * * _.merge(users, ages); * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } * * var food = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var otherFood = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * _.merge(food, otherFood, function(a, b) { * return _.isArray(a) ? a.concat(b) : undefined; * }); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } */ var merge = createAssigner(baseMerge); /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of * property names. If a predicate is provided it is invoked for each property * of `object` omitting the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Object * @param {Object} object The source object. * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns the new object. * @example * * _.omit({ 'user': 'fred', 'age': 40 }, 'age'); * // => { 'user': 'fred' } * * _.omit({ 'user': 'fred', 'age': 40 }, function(value) { * return typeof value == 'number'; * }); * // => { 'user': 'fred' } */ function omit(object, predicate, thisArg) { if (object == null) { return {}; } var iterable = toObject(object); if (typeof predicate != 'function') { var props = arrayMap(baseFlatten(arguments, false, false, 1), String); return pickByArray(iterable, baseDifference(keysIn(iterable), props)); } predicate = getCallback(predicate, thisArg, 3); return pickByCallback(iterable, function(value, key, object) { return !predicate(value, key, object); }); } /** * Creates a two dimensional array of a given object's key-value pairs, * e.g. `[[key1, value1], [key2, value2]]`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the new array of key-value pairs. * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) */ function pairs(object) { var index = -1, props = keys(object), length = props.length, result = Array(length); while (++index < length) { var key = props[index]; result[index] = [key, object[key]]; } return result; } /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of * property names. If a predicate is provided it is invoked for each property * of `object` picking the properties the predicate returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Object * @param {Object} object The source object. * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns the new object. * @example * * _.pick({ 'user': 'fred', '_userid': 'fred1' }, 'user'); * // => { 'user': 'fred' } * * _.pick({ 'user': 'fred', '_userid': 'fred1' }, function(value, key) { * return key.charAt(0) != '_'; * }); * // => { 'user': 'fred' } */ function pick(object, predicate, thisArg) { if (object == null) { return {}; } var iterable = toObject(object); return typeof predicate == 'function' ? pickByCallback(iterable, getCallback(predicate, thisArg, 3)) : pickByArray(iterable, baseFlatten(arguments, false, false, 1)); } /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own * enumerable properties through `iteratee`, with each invocation potentially * mutating the `accumulator` object. The `iteratee` is bound to `thisArg` * and invoked with four arguments; (accumulator, value, key, object). Iterator * functions may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. * @param {Function} [iteratee=identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * var squares = _.transform([1, 2, 3, 4, 5, 6], function(result, n) { * n *= n; * if (n % 2) { * return result.push(n) < 3; * } * }); * // => [1, 9, 25] * * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { * result[key] = n * 3; * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ function transform(object, iteratee, accumulator, thisArg) { iteratee = getCallback(iteratee, thisArg, 4); var isArr = isArrayLike(object); if (accumulator == null) { if (isArr) { accumulator = []; } else if (isObject(object)) { var Ctor = object.constructor; accumulator = baseCreate(typeof Ctor == 'function' && Ctor.prototype); } else { accumulator = {}; } } (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { return iteratee(accumulator, value, index, object); }); return accumulator; } /** * Creates an array of the own enumerable property values of `object`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property values. * @example * * function Shape(x, y) { * this.x = x; * this.y = y; * } * * Shape.prototype.z = 0; * * _.values(new Shape(2, 1)); * // => [2, 1] (iteration order is not guaranteed) */ function values(object) { return baseValues(object, keys); } /** * Creates an array of the own and inherited enumerable property values * of `object`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property values. * @example * * function Shape(x, y) { * this.x = x; * this.y = y; * } * * Shape.prototype.z = 0; * * _.valuesIn(new Shape(2, 1)); * // => [2, 1, 0] (iteration order is not guaranteed) */ function valuesIn(object) { return baseValues(object, keysIn); } /*------------------------------------------------------------------------*/ /** * Converts `string` to camel case. * See [Wikipedia](http://en.wikipedia.org/wiki/CamelCase) for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to camel case. * @returns {string} Returns the camel cased string. * @example * * _.camelCase('Hello world'); * // => 'helloWorld' * * _.camelCase('--hello-world'); * // => 'helloWorld' * * _.camelCase('__hello_world__'); * // => 'helloWorld' */ var camelCase = createCompounder(function(result, word, index) { word = word.toLowerCase(); return index ? (result + word.charAt(0).toUpperCase() + word.slice(1)) : word; }); /** * Capitalizes the first character of `string`. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to capitalize. * @returns {string} Returns the capitalized string. * @example * * _.capitalize('fred'); * // => 'Fred' */ function capitalize(string) { string = string == null ? '' : String(string); return string ? (string.charAt(0).toUpperCase() + string.slice(1)) : string; } /** * Deburrs `string` by converting latin-1 supplementary letters to basic latin letters. * See [Wikipedia](http://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) * for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to deburr. * @returns {string} Returns the beburred string. * @example * * _.deburr('déjà vu'); * // => 'deja vu' */ function deburr(string) { string = string == null ? '' : String(string); return string ? string.replace(reLatin1, deburrLetter) : string; } /** * Checks if `string` ends with a given target string. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=string.length] The position to search from. * @returns {boolean} Returns `true` if the given string ends with the * target string, else `false`. * @example * * _.endsWith('abc', 'c'); * // => true * * _.endsWith('abc', 'b'); * // => false * * _.endsWith('abc', 'b', 2); * // => true */ function endsWith(string, target, position) { string = string == null ? '' : String(string); target = String(target); var length = string.length; position = (typeof position == 'undefined' ? length : nativeMin(position < 0 ? 0 : (+position || 0), length)) - target.length; return position >= 0 && string.indexOf(target, position) == position; } /** * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional characters * use a third-party library like [_he_](http://mths.be/he). * * When working with HTML you should always quote attribute values to reduce * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) * for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escape('fred, barney, & pebbles'); * // => 'fred, barney, & pebbles' */ function escape(string) { // reset `lastIndex` because in IE < 9 `String#replace` does not string = string == null ? '' : String(string); return string && (reUnescapedHtml.lastIndex = 0, reUnescapedHtml.test(string)) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; } /** * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", * "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escapeRegExp('[lodash](http://lodash.com/)'); * // => '\[lodash\]\(http://lodash\.com/\)' */ function escapeRegExp(string) { string = string == null ? '' : String(string); return string && (reRegExpChars.lastIndex = 0, reRegExpChars.test(string)) ? string.replace(reRegExpChars, '\\$&') : string; } /** * Converts `string` to kebab case (a.k.a. spinal case). * See [Wikipedia](http://en.wikipedia.org/wiki/Letter_case#Computers) for * more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to kebab case. * @returns {string} Returns the kebab cased string. * @example * * _.kebabCase('Hello world'); * // => 'hello-world' * * _.kebabCase('helloWorld'); * // => 'hello-world' * * _.kebabCase('__hello_world__'); * // => 'hello-world' */ var kebabCase = createCompounder(function(result, word, index) { return result + (index ? '-' : '') + word.toLowerCase(); }); /** * Pads `string` on the left and right sides if it is shorter then the given * padding length. The `chars` string may be truncated if the number of padding * characters can't be evenly divided by the padding length. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.pad('abc', 8); * // => ' abc ' * * _.pad('abc', 8, '_-'); * // => '_-abc_-_' * * _.pad('abc', 3); * // => 'abc' */ function pad(string, length, chars) { string = string == null ? '' : String(string); length = +length; var strLength = string.length; if (strLength >= length || !nativeIsFinite(length)) { return string; } var mid = (length - strLength) / 2, leftLength = floor(mid), rightLength = ceil(mid); chars = createPad('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; } /** * Pads `string` on the left side if it is shorter then the given padding * length. The `chars` string may be truncated if the number of padding * characters exceeds the padding length. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padLeft('abc', 6); * // => ' abc' * * _.padLeft('abc', 6, '_-'); * // => '_-_abc' * * _.padLeft('abc', 3); * // => 'abc' */ function padLeft(string, length, chars) { string = string == null ? '' : String(string); return string ? (createPad(string, length, chars) + string) : string; } /** * Pads `string` on the right side if it is shorter then the given padding * length. The `chars` string may be truncated if the number of padding * characters exceeds the padding length. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padRight('abc', 6); * // => 'abc ' * * _.padRight('abc', 6, '_-'); * // => 'abc_-_' * * _.padRight('abc', 3); * // => 'abc' */ function padRight(string, length, chars) { string = string == null ? '' : String(string); return string ? (string + createPad(string, length, chars)) : string; } /** * Repeats the given string `n` times. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to repeat. * @param {number} [n=0] The number of times to repeat the string. * @returns {string} Returns the repeated string. * @example * * _.repeat('*', 3); * // => '***' * * _.repeat('abc', 2); * // => 'abcabc' * * _.repeat('abc', 0); * // => '' */ function repeat(string, n) { var result = ''; n = +n; if (n < 1 || string == null || !nativeIsFinite(n)) { return result; } string = String(string); // leverage the exponentiation by squaring algorithm for a faster repeat // http://en.wikipedia.org/wiki/Exponentiation_by_squaring do { if (n % 2) { result += string; } n = floor(n / 2); string += string; } while (n); return result; } /** * Converts `string` to snake case. * See [Wikipedia](http://en.wikipedia.org/wiki/Snake_case) for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to snake case. * @returns {string} Returns the snake cased string. * @example * * _.snakeCase('Hello world'); * // => 'hello_world' * * _.snakeCase('--hello-world'); * // => 'hello_world' * * _.snakeCase('helloWorld'); * // => 'hello_world' */ var snakeCase = createCompounder(function(result, word, index) { return result + (index ? '_' : '') + word.toLowerCase(); }); /** * Checks if `string` starts with a given target string. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. * @returns {boolean} Returns `true` if the given string starts with the * target string, else `false`. * @example * * _.startsWith('abc', 'a'); * // => true * * _.startsWith('abc', 'b'); * // => false * * _.startsWith('abc', 'b', 1); * // => true */ function startsWith(string, target, position) { string = string == null ? '' : String(string); position = typeof position == 'undefined' ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length); return string.lastIndexOf(target, position) == position; } /** * Creates a compiled template function that can interpolate data properties * 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 overrides `_.templateSettings` for the template. * * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * * For more information on precompiling templates see * [Lo-Dash's custom builds documentation](http://lodash.com/custom-builds). * * For more information on Chrome extension sandboxes see * [Chrome's extensions documentation](http://developer.chrome.com/stable/extensions/sandboxingEval.html). * * @static * @memberOf _ * @category String * @param {string} [string=''] The template string. * @param {Object} [options] The options object. * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. * @param {Object} [options.imports] An object to import into the template as free variables. * @param {RegExp} [options.interpolate] The "interpolate" delimiter. * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. * @param {string} [options.variable] The data object variable name. * @param- {Object} [otherOptions] Enables the legacy `options` param signature. * @returns {Function} Returns the compiled template function. * @example * * // using the "interpolate" delimiter to create a compiled template * var compiled = _.template('hello <%= name %>'); * compiled({ 'user': 'fred' }); * // => 'hello fred' * * // using the HTML "escape" delimiter to escape data property values * var compiled = _.template('<%- value %>'); * compiled({ 'value': '