diff --git a/lodash.js b/lodash.js
index 02cac1c28..673d90749 100644
--- a/lodash.js
+++ b/lodash.js
@@ -3,7 +3,7 @@
* Lo-Dash 2.4.1
* Copyright 2012-2014 The Dojo Foundation
* Based on Underscore.js 1.6.0
- * Copyright 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license
*/
;(function() {
@@ -25,15 +25,9 @@
/** Used as the property name for wrapper metadata */
var expando = '__lodash@' + version + '__';
- /** Used as the TypeError message for "Functions" methods */
- var funcErrorText = 'Expected a function';
-
/** Used to generate unique IDs */
var idCounter = 0;
- /** Used to detect words composed of all capital letters */
- var reAllCaps = /^[A-Z]+$/;
-
/** Used to match empty string literals in compiled template source */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
@@ -49,13 +43,12 @@
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.
+ * Used to match ES6 template delimiters
+ * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
- /** Used to match `RegExp` flags from their coerced string values */
+ /** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
/** Used to detected named functions */
@@ -64,27 +57,14 @@
/** Used to detect hexadecimal string values */
var reHexPrefix = /^0[xX]/;
- /** 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 = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[a-z]+|[0-9]+/g;
+ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/** Used to detect and test whitespace */
var whitespace = (
@@ -105,13 +85,13 @@
'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError'
];
- /** Used to fix the JScript `[[DontEnum]]` bug */
+ /** Used to fix the JScript [[DontEnum]] bug */
var shadowedProps = [
'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
'toLocaleString', 'toString', 'valueOf'
];
- /** Used to make template `sourceURL`s easier to identify */
+ /** Used to make template sourceURLs easier to identify */
var templateCounter = 0;
/** `Object#toString` result shortcuts */
@@ -134,7 +114,7 @@
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
- /** Used as an internal `_.debounce` options object by `_.throttle` */
+ /** Used as an internal `_.debounce` options object */
var debounceOptions = {
'leading': false,
'maxWait': 0,
@@ -175,32 +155,7 @@
''': "'"
};
- /**
- * Used to convert latin-1 supplement letters to basic latin (ASCII) letters.
- * See [Wikipedia](http://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
- * for more details.
- */
- 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` */
+ /** Used to determine if values are of the language type Object */
var objectTypes = {
'function': true,
'object': true
@@ -212,6 +167,7 @@
"'": "'",
'\n': 'n',
'\r': 'r',
+ '\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
@@ -236,33 +192,21 @@
/*--------------------------------------------------------------------------*/
- /**
- * 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;
- }
-
/**
* The base implementation of `compareAscending` used to compare values and
* sort 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`.
+ * @param {*} a The value to compare to `b`.
+ * @param {*} b The value to compare to `a`.
+ * @returns {number} Returns the sort order indicator for `a`.
*/
- function baseCompareAscending(value, other) {
- if (value !== other) {
- if (value > other || typeof value == 'undefined') {
+ function baseCompareAscending(a, b) {
+ if (a !== b) {
+ if (a > b || typeof a == 'undefined') {
return 1;
}
- if (value < other || typeof other == 'undefined') {
+ if (a < b || typeof b == 'undefined') {
return -1;
}
}
@@ -276,7 +220,7 @@
* @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`.
+ * @returns {number} Returns the index of the matched value or `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
@@ -304,24 +248,22 @@
}
/**
- * Used by `_.max` and `_.min` as the default callback when a given collection
- * is a string value.
+ * 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.
+ * @param {string} value The character to inspect.
+ * @returns {number} Returns the code unit of given character.
*/
- function charAtCallback(string) {
- return string.charCodeAt(0);
+ function charAtCallback(value) {
+ return value.charCodeAt(0);
}
/**
- * Used by `_.trim` and `_.trimLeft` to get the index of the first character
- * of `string` that is not found in `chars`.
+ * Gets 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) {
@@ -337,12 +279,10 @@
}
/**
- * Used by `_.trim` and `_.trimRight` to get the index of the last character
- * of `string` that is not found in `chars`.
+ * Gets 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) {
@@ -356,103 +296,69 @@
}
/**
- * Used by `_.sortBy` to compare transformed elements of a collection and stable
+ * Used by `sortBy` to compare transformed elements of 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`.
+ * @param {Object} a The object to compare to `b`.
+ * @param {Object} b The object to compare to `a`.
+ * @returns {number} Returns the sort order indicator for `a`.
*/
- function compareAscending(object, other) {
- return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index;
+ function compareAscending(a, b) {
+ return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index;
}
/**
- * Used by `_.sortBy` to compare multiple properties of each element in a
+ * 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`.
+ * @param {Object} a The object to compare to `b`.
+ * @param {Object} b The object to compare to `a`.
+ * @returns {number} Returns the sort order indicator for `a`.
*/
- function compareMultipleAscending(object, other) {
- var index = -1,
- objCriteria = object.criteria,
- othCriteria = other.criteria,
- length = objCriteria.length;
+ function compareMultipleAscending(a, b) {
+ var ac = a.criteria,
+ bc = b.criteria,
+ index = -1,
+ length = ac.length;
while (++index < length) {
- var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
+ var result = baseCompareAscending(ac[index], bc[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
+ // that causes it, under certain circumstances, to provided the same value
+ // for `a` and `b`. 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;
+ return a.index - b.index;
}
/**
- * Creates a function that produces compound words out of the words in a
- * given string.
+ * Used by `escape` to convert characters to HTML entities.
*
* @private
- * @param {Function} callback The function called to combine each word.
- * @returns {Function} Returns the new compounder function.
- */
- function createCompounder(callback) {
- return function(string) {
- var index = -1,
- words = string != null && String(string).replace(reLatin1, deburrLetter).match(reWords),
- length = words ? words.length : 0,
- result = '';
-
- while (++index < length) {
- result = callback(result, words[index], index, words);
- }
- return result;
- };
- }
-
- /**
- * Used by `createCompounder` to convert latin-1 supplement letters to basic
- * latin (ASCII) 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.
+ * @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
- function escapeHtmlChar(chr) {
- return htmlEscapes[chr];
+ function escapeHtmlChar(match) {
+ return htmlEscapes[match];
}
/**
- * Used by `_.template` to escape characters for inclusion in compiled
+ * Used by `template` to escape characters for inclusion in compiled
* string literals.
*
* @private
- * @param {string} chr The matched character to escape.
+ * @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
- function escapeStringChar(chr) {
- return '\\' + stringEscapes[chr];
+ function escapeStringChar(match) {
+ return '\\' + stringEscapes[match];
}
/**
@@ -460,7 +366,7 @@
*
* @private
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a DOM node, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`.
*/
function isNode(value) {
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
@@ -469,8 +375,70 @@
}
/**
- * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
- * character of `string`.
+ * A fallback implementation of `trim` to remove leading and trailing
+ * whitespace or specified characters from `string`.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @returns {string} Returns the trimmed string.
+ */
+ function shimTrim(string, chars) {
+ string = string == null ? '' : String(string);
+ if (!string) {
+ return string;
+ }
+ if (chars == null) {
+ return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);
+ }
+ chars = String(chars);
+ return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);
+ }
+
+ /**
+ * A fallback implementation of `trimLeft` to remove leading whitespace or
+ * specified characters from `string`.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @returns {string} Returns the trimmed string.
+ */
+ function shimTrimLeft(string, chars) {
+ string = string == null ? '' : String(string);
+ if (!string) {
+ return string;
+ }
+ if (chars == null) {
+ return string.slice(trimmedLeftIndex(string))
+ }
+ chars = String(chars);
+ return string.slice(charsLeftIndex(string, chars));
+ }
+
+ /**
+ * A fallback implementation of `trimRight` to remove trailing whitespace or
+ * specified characters from `string`.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @returns {string} Returns the trimmed string.
+ */
+ function shimTrimRight(string, chars) {
+ string = string == null ? '' : String(string);
+ if (!string) {
+ return string;
+ }
+ if (chars == null) {
+ return string.slice(0, trimmedRightIndex(string) + 1)
+ }
+ chars = String(chars);
+ return string.slice(0, charsRightIndex(string, chars) + 1);
+ }
+
+ /**
+ * Gets the index of the first non-whitespace character of `string`.
*
* @private
* @param {string} string The string to inspect.
@@ -491,8 +459,7 @@
}
/**
- * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
- * character of `string`.
+ * Gets the index of the last non-whitespace character of `string`.
*
* @private
* @param {string} string The string to inspect.
@@ -511,20 +478,20 @@
}
/**
- * Used by `_.unescape` to convert HTML entities to characters.
+ * Used by `unescape` to convert HTML entities to characters.
*
* @private
- * @param {string} chr The matched character to unescape.
+ * @param {string} match The matched character to unescape.
* @returns {string} Returns the unescaped character.
*/
- function unescapeHtmlChar(chr) {
- return htmlUnescapes[chr];
+ function unescapeHtmlChar(match) {
+ return htmlUnescapes[match];
}
/*--------------------------------------------------------------------------*/
/**
- * Create a new `lodash` function using the given `context` object.
+ * Create a new `lodash` function using the given context object.
*
* @static
* @memberOf _
@@ -561,23 +528,17 @@
/** Used to detect DOM support */
var document = (document = context.window) && document.document;
- /** Used to restore the original `_` reference in `_.noConflict` */
+ /** Used to restore the original `_` reference in `noConflict` */
var oldDash = context._;
- /**
- * Used as the maximum length of an array-like object.
- * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
- * for more details.
- */
- var maxSafeInteger = Math.pow(2, 53) - 1;
-
- /** Used to resolve the internal `[[Class]]` of values */
+ /** 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.*?') + '$'
+ String(toString)
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+ .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
/** Native method shortcuts */
@@ -594,7 +555,7 @@
splice = arrayRef.splice,
unshift = arrayRef.unshift;
- /** Used to set metadata on functions */
+ /** Used to set meta data on functions */
var defineProperty = (function() {
// IE 8 only accepts DOM elements
try {
@@ -616,9 +577,12 @@
nativeMin = Math.min,
nativeNow = isNative(nativeNow = Date.now) && nativeNow,
nativeParseInt = context.parseInt,
- nativeRandom = Math.random;
+ nativeRandom = Math.random,
+ nativeTrim = isNative(nativeTrim = stringProto.trim) && !nativeTrim.call(whitespace) && nativeTrim,
+ nativeTrimLeft = isNative(nativeTrimLeft = stringProto.trimLeft) && !nativeTrimLeft.call(whitespace) && nativeTrimLeft,
+ nativeTrimRight = isNative(nativeTrimRight = stringProto.trimRight) && !nativeTrimRight.call(whitespace) && nativeTrimRight;
- /** Used to lookup built-in constructors by `[[Class]]` */
+ /** Used to lookup a built-in constructor by [[Class]] */
var ctorByClass = {};
ctorByClass[arrayClass] = Array;
ctorByClass[boolClass] = Boolean;
@@ -629,7 +593,7 @@
ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String;
- /** Used to avoid iterating over non-enumerable properties in IE < 9 */
+ /** Used to avoid iterating 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 };
@@ -662,18 +626,18 @@
* implicitly or explicitly included in the build.
*
* The chainable wrapper functions are:
- * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
+ * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
* `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`,
* `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`,
* `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`,
* `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`,
* `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`,
- * `merge`, `min`, `mixin`, `noop`, `object`, `omit`, `once`, `pairs`,
- * `partial`, `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`,
- * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
- * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
- * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
- * `xor`, and `zip`
+ * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`,
+ * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`,
+ * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`,
+ * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`,
+ * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`,
+ * and `zip`
*
* The non-chainable wrapper functions are:
* `capitalize`, `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`,
@@ -681,10 +645,10 @@
* `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`,
* `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`,
* `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`,
- * `isUndefined`, `join`, `lastIndexOf`, `noConflict`, `now`, `parseInt`,
- * `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`,
- * `sortedIndex`, `runInContext`, `template`, `trim`, `trimLeft`, `trimRight`,
- * `unescape`, `uniqueId`, and `value`
+ * `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `now`,
+ * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`,
+ * `size`, `some`, `sortedIndex`, `runInContext`, `template`, `trim`,
+ * `trimLeft`, `trimRight`, `unescape`, `uniqueId`, and `value`
*
* The wrapper functions `first`, `last`, and `sample` return wrapped values
* when `n` is provided, otherwise they return unwrapped values.
@@ -729,7 +693,7 @@
*
* @private
* @param {*} value The value to wrap in a `lodash` instance.
- * @param {boolean} [chainAll=false] A flag to enable chaining for all methods.
+ * @param {boolean} [chainAll=false] A flag to enable chaining for all methods
* @returns {Object} Returns a `lodash` instance.
*/
function lodashWrapper(value, chainAll) {
@@ -748,19 +712,17 @@
*/
var support = lodash.support = {};
- (function(x) {
+ (function() {
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); }
- for (var argsKey in arguments) { }
- for (var strKey in 'x') { }
+ for (key in arguments) { }
/**
- * Detect if the `[[Class]]` of `arguments` objects is resolvable
- * (all but Firefox < 4, IE < 9).
+ * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9).
*
* @memberOf _.support
* @type boolean
@@ -768,8 +730,7 @@
support.argsClass = toString.call(arguments) == argsClass;
/**
- * Detect if `arguments` objects are `Object` objects
- * (all but Narwhal and Opera < 10.5).
+ * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5).
*
* @memberOf _.support
* @type boolean
@@ -778,21 +739,20 @@
/**
* Detect if `name` or `message` properties of `Error.prototype` are
- * enumerable by default (IE < 9, Safari < 5.1).
+ * enumerable by default. (IE < 9, Safari < 5.1)
*
* @memberOf _.support
* @type boolean
*/
- support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') ||
- propertyIsEnumerable.call(errorProto, 'name');
+ 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`.
+ * incorrectly sets a function's `prototype` property [[Enumerable]]
+ * value to `true`.
*
* @memberOf _.support
* @type boolean
@@ -801,8 +761,7 @@
/**
* 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).
+ * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
*
* @memberOf _.support
* @type boolean
@@ -818,20 +777,19 @@
support.funcNames = typeof Function.name == 'string';
/**
- * Detect if string indexes are non-enumerable
- * (IE < 9, RingoJS, Rhino, Narwhal).
+ * Detect if `arguments` object indexes are non-enumerable
+ * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1).
*
* @memberOf _.support
* @type boolean
*/
- support.nonEnumStrings = strKey != '0';
+ support.nonEnumArgs = key != 0;
/**
- * Detect if properties shadowing those on `Object.prototype` are
- * non-enumerable.
+ * 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).
+ * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+ * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).
*
* @memberOf _.support
* @type boolean
@@ -839,8 +797,7 @@
support.nonEnumShadows = !/valueOf/.test(props);
/**
- * Detect if own properties are iterated after inherited properties
- * (all but IE < 9).
+ * Detect if own properties are iterated after inherited properties (all but IE < 9).
*
* @memberOf _.support
* @type boolean
@@ -848,15 +805,13 @@
support.ownLast = props[0] != 'x';
/**
- * Detect if `Array#shift` and `Array#splice` augment array-like objects
- * correctly.
+ * 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.
+ * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
*
* @memberOf _.support
* @type boolean
@@ -866,8 +821,8 @@
/**
* 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.
+ * IE < 8 can't access characters by index and IE 8 can only access
+ * characters by index on string literals.
*
* @memberOf _.support
* @type boolean
@@ -887,9 +842,9 @@
}
/**
- * Detect if the `[[Class]]` of DOM nodes is resolvable (all but IE < 9)
- * and that the JS engine errors when attempting to coerce an object to a
- * string without a `toString` function.
+ * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9)
+ * and that the JS engine errors when attempting to coerce an object to
+ * a string without a `toString` function.
*
* @memberOf _.support
* @type boolean
@@ -899,31 +854,12 @@
} catch(e) {
support.nodeClass = true;
}
-
- /**
- * 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 = !(argsKey == '1' && hasOwnProperty.call(arguments, argsKey) &&
- propertyIsEnumerable.call(arguments, argsKey));
- } catch(e) {
- support.nonEnumArgs = true;
- }
- }(0, 0));
+ }(1));
/**
- * 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.
+ * 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 _
@@ -984,68 +920,88 @@
/*--------------------------------------------------------------------------*/
/**
- * A specialized version of `_.forEach` for arrays without support for
- * callback shorthands or `this` binding.
+ * The template used to create iterator functions.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {Array} Returns `array`.
+ * @param {Object} data The data object used to populate the text.
+ * @returns {string} Returns the interpolated text.
*/
- function arrayEach(array, callback) {
- var index = -1,
- length = array ? array.length : 0;
+ var iteratorTemplate = template(
+ // assign the `result` variable an initial value
+ 'var result = <%= init %>;\n' +
- while (++index < length) {
- if (callback(array[index], index, array) === false) {
- break;
- }
- }
- return array;
- }
+ // exit early if the first argument is not an object
+ "if (!isObject(object)) {\n" +
+ ' return result;\n' +
+ '}' +
- /**
- * 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} callback The function called per iteration.
- * @returns {Array} Returns `array`.
- */
- function arrayEachRight(array, callback) {
- var length = array ? array.length : 0;
- while (length--) {
- if (callback(array[length], length, array) === false) {
- break;
- }
- }
- return array;
- }
+ // add support for iterating over `arguments` objects if needed
+ '<% if (support.nonEnumArgs) { %>\n' +
+ 'var length = object.length;\n' +
+ 'if (length && isArguments(object)) {\n' +
+ ' key = -1;\n' +
+ ' while (++key < length) {\n' +
+ " key += '';\n" +
+ ' <%= loop %>;\n' +
+ ' }\n' +
+ ' return result;\n' +
+ '}' +
+ '<% } %>' +
- /**
- * 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} callback The function called per iteration.
- * @returns {Array} Returns the new mapped array.
- */
- function arrayMap(array, callback) {
- var index = -1,
- length = array ? array.length >>> 0 : 0,
- result = Array(length);
+ // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari
+ '<% if (support.enumPrototypes) { %>\n' +
+ "var skipProto = typeof object == 'function';\n" +
+ '<% } %>' +
- while (++index < length) {
- result[index] = callback(array[index], index, array);
- }
- return result;
- }
+ // avoid iterating over `Error.prototype` properties in older IE and Safari
+ '<% if (support.enumErrorProps) { %>\n' +
+ 'var skipErrorProps = object === errorProto || object instanceof Error;\n' +
+ '<% } %>' +
+
+ // define conditions used in the loop
+ '<%' +
+ 'var conditions = [];\n' +
+ "if (support.enumPrototypes) { conditions.push('!(skipProto && key == \\'prototype\\')'); }\n" +
+ "if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (key == \\'message\\' || key == \\'name\\'))'); }" +
+ '%>\n' +
+
+ // iterate over the object
+ 'for (var key in object) {\n<%' +
+ " if (useHas) { conditions.push('hasOwnProperty.call(object, key)'); }\n" +
+ " if (conditions.length) { %> if (<%= conditions.join(' && ') %>) {\n <% } %>" +
+ ' <%= loop %>;' +
+ ' <% if (conditions.length) { %>\n }<% } %>\n' +
+ '}\n' +
+
+ // Lo-Dash skips the `constructor` property when it infers it's 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.
+ '<% if (support.nonEnumShadows) { %>\n' +
+ 'if (object !== objectProto) {\n' +
+ " var ctor = object.constructor,\n" +
+ ' isProto = object === (ctor && ctor.prototype),\n' +
+ ' className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object),\n' +
+ ' nonEnum = nonEnumProps[className];\n' +
+ ' <% for (var index = 0; index < 7; index++) { %>\n' +
+ " key = '<%= shadowedProps[index] %>';\n" +
+ ' if ((!(isProto && nonEnum[key]) && hasOwnProperty.call(object, key))<%' +
+ ' if (!useHas) { %> || (!nonEnum[key] && object[key] !== objectProto[key])<% }' +
+ ' %>) {\n' +
+ ' <%= loop %>;\n' +
+ ' }' +
+ ' <% } %>\n' +
+ '}' +
+ '<% } %>\n' +
+
+ 'return result;'
+ );
+
+ /*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.bind` that creates the bound function and
- * sets its metadata.
+ * sets its meta data.
*
* @private
* @param {Array} data The metadata array.
@@ -1064,8 +1020,8 @@
// avoid `arguments` object use disqualifying optimizations by
// converting it to an array before passing it to `composeArgs`
var index = -1,
- length = arguments.length,
- args = Array(length);
+ length = arguments.length,
+ args = Array(length);
while (++index < length) {
args[index] = arguments[index];
@@ -1089,7 +1045,7 @@
/**
* The base implementation of `_.clone` without argument juggling or support
- * for `this` binding.
+ * for `thisArg` binding.
*
* @private
* @param {*} value The value to clone.
@@ -1106,6 +1062,7 @@
return result;
}
}
+ // inspect [[Class]]
var isObj = isObject(value);
if (isObj) {
var className = toString.call(value);
@@ -1133,6 +1090,7 @@
var isArr = isArray(value);
if (isDeep) {
// check for circular references and return corresponding clone
+ var initedStack = !stackA;
stackA || (stackA = []);
stackB || (stackB = []);
@@ -1166,8 +1124,8 @@
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
- (isArr ? arrayEach : baseForOwn)(value, function(valValue, key) {
- result[key] = baseClone(valValue, isDeep, callback, stackA, stackB);
+ (isArr ? baseEach : baseForOwn)(value, function(objValue, key) {
+ result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
});
return result;
@@ -1207,7 +1165,7 @@
* @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.
+ * @returns {Function} Returns a callback function.
*/
function baseCreateCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
@@ -1243,8 +1201,8 @@
case 1: return function(value) {
return func.call(thisArg, value);
};
- case 2: return function(value, other) {
- return func.call(thisArg, value, other);
+ case 2: return function(a, b) {
+ return func.call(thisArg, a, b);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
@@ -1258,7 +1216,7 @@
/**
* The base implementation of `createWrapper` that creates the wrapper and
- * sets its metadata.
+ * sets its meta data.
*
* @private
* @param {Array} data The metadata array.
@@ -1294,19 +1252,14 @@
if (partialRightArgs) {
args = composeArgsRight(partialRightArgs, partialRightHolders, args);
}
- if (isCurry) {
- var newPartialHolders = getHolders(args);
- length -= newPartialHolders.length;
-
- if (length < arity) {
- bitmask |= PARTIAL_FLAG;
- bitmask &= ~PARTIAL_RIGHT_FLAG
- if (!isCurryBound) {
- bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
- }
- var newArity = nativeMax(arity - length, 0);
- return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, newPartialHolders]);
+ if (isCurry && length < arity) {
+ bitmask |= PARTIAL_FLAG;
+ bitmask &= ~PARTIAL_RIGHT_FLAG
+ if (!isCurryBound) {
+ bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
}
+ var newArity = nativeMax(0, arity - length);
+ return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, []]);
}
var thisBinding = isBind ? thisArg : this;
if (isBindKey) {
@@ -1330,7 +1283,7 @@
* @private
* @param {Array} array The array to process.
* @param {Array} [values] The array of values to exclude.
- * @returns {Array} Returns the new array of filtered values.
+ * @returns {Array} Returns a new array of filtered values.
*/
function baseDifference(array, values) {
var length = array ? array.length : 0;
@@ -1371,7 +1324,7 @@
/**
* The base implementation of `_.forEach` without support for callback
- * shorthands or `this` binding.
+ * shorthands or `thisArg` binding.
*
* @private
* @param {Array|Object|string} collection The collection to iterate over.
@@ -1383,7 +1336,7 @@
iterable = collection,
length = collection ? collection.length : 0;
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ if (typeof length == 'number') {
if (support.unindexedChars && isString(iterable)) {
iterable = iterable.split('');
}
@@ -1400,7 +1353,7 @@
/**
* The base implementation of `_.forEachRight` without support for callback
- * shorthands or `this` binding.
+ * shorthands or `thisArg` binding.
*
* @private
* @param {Array|Object|string} collection The collection to iterate over.
@@ -1411,7 +1364,7 @@
var iterable = collection,
length = collection ? collection.length : 0;
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ if (typeof length == 'number') {
if (support.unindexedChars && isString(iterable)) {
iterable = iterable.split('');
}
@@ -1426,41 +1379,16 @@
return collection;
}
- /**
- * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`
- * without support for callback shorthands or `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 called per iteration.
- * @param {Function} eachFunc The function to iterate over the collection.
- * @param {boolean} [retKey=false] A flag to indicate 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` without support for callback
- * shorthands or `this` binding.
+ * shorthands or `thisArg` binding.
*
* @private
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
* @param {number} [fromIndex=0] The index to start from.
- * @returns {Array} Returns the new flattened array.
+ * @returns {Array} Returns a new flattened array.
*/
function baseFlatten(array, isShallow, isStrict, fromIndex) {
var index = (fromIndex || 0) - 1,
@@ -1492,20 +1420,17 @@
}
/**
- * The base implementation of `baseForIn` and `baseForOwn` which iterates
- * over `object` properties returned by `keysFunc` executing the callback
- * for each property. Callbacks may exit iteration early by explicitly
- * returning `false`.
+ * The base implementation of `_.forOwn` without support for callback
+ * shorthands or `thisArg` binding.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} callback The function called per iteration.
- * @param {Function} keysFunc The function to get the keys of `object`.
* @returns {Object} Returns `object`.
*/
- function baseFor(object, callback, keysFunc) {
+ function baseForOwn(object, callback) {
var index = -1,
- props = keysFunc(object),
+ props = keys(object),
length = props.length;
while (++index < length) {
@@ -1518,17 +1443,16 @@
}
/**
- * This function is like `baseFor` except that it iterates over properties
- * in the opposite order.
+ * The base implementation of `_.forOwnRight` without support for callback
+ * shorthands or `thisArg` binding.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} callback The function called per iteration.
- * @param {Function} keysFunc The function to get the keys of `object`.
* @returns {Object} Returns `object`.
*/
- function baseForRight(object, callback, keysFunc) {
- var props = keysFunc(object),
+ function baseForOwnRight(object, callback) {
+ var props = keys(object),
length = props.length;
while (length--) {
@@ -1541,190 +1465,137 @@
}
/**
- * The base implementation of `_.forIn` without support for callback
- * shorthands or `this` binding.
+ * The base implementation of `_.isEqual`, without support for `thisArg` binding,
+ * that allows partial "_.where" style comparisons.
*
* @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {Object} Returns `object`.
- */
- function baseForIn(object, callback) {
- return baseFor(object, callback, keysIn);
- }
-
- /**
- * The base implementation of `_.forOwn` without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {Object} Returns `object`.
- */
- function baseForOwn(object, callback) {
- return baseFor(object, callback, keys);
- }
-
- /**
- * The base implementation of `_.forOwnRight` without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} callback The function called per iteration.
- * @returns {Object} Returns `object`.
- */
- function baseForOwnRight(object, callback) {
- return baseForRight(object, callback, keys);
- }
-
- /**
- * The base implementation of `_.isEqual`, without support for `thisArg`
- * binding, that allows partial "_.where" style comparisons.
- *
- * @private
- * @param {*} value The value to compare to `other`.
- * @param {*} other The value to compare to `value`.
+ * @param {*} a The value to compare.
+ * @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
- * @param {Array} [stackA=[]] Tracks traversed `value` objects.
- * @param {Array} [stackB=[]] Tracks traversed `other` objects.
+ * @param {Array} [stackA=[]] Tracks traversed `a` objects.
+ * @param {Array} [stackB=[]] Tracks traversed `b` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
- function baseIsEqual(value, other, callback, isWhere, stackA, stackB) {
+ function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
if (callback) {
- var result = callback(value, other);
+ var result = callback(a, b);
if (typeof result != 'undefined') {
return !!result;
}
}
// exit early for identical values
- if (value === other) {
+ if (a === b) {
// treat `+0` vs. `-0` as not equal
- return value !== 0 || (1 / value == 1 / other);
+ return a !== 0 || (1 / a == 1 / b);
}
- var valType = typeof value,
- othType = typeof other;
+ var type = typeof a,
+ otherType = typeof b;
// exit early for unlike primitive values
- if (value === value && (value == null || other == null ||
- (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) {
+ if (a === a && (a == null || b == null ||
+ (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) {
return false;
}
- var valClass = toString.call(value),
- othClass = toString.call(other),
- valIsArg = valClass == argsClass,
- othIsArg = othClass == argsClass;
+ // compare [[Class]] names
+ var className = toString.call(a),
+ otherClass = toString.call(b);
- if (valIsArg) {
- valClass = objectClass;
+ if (className == argsClass) {
+ className = objectClass;
}
- if (othIsArg) {
- othClass = objectClass;
+ if (otherClass == argsClass) {
+ otherClass = objectClass;
}
- if (valClass != othClass) {
+ if (className != otherClass) {
return false;
}
- switch (valClass) {
+ switch (className) {
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;
+ return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
- return (value != +value)
- ? other != +other
+ return (a != +a)
+ ? b != +b
// but treat `-0` vs. `+0` as not equal
- : (value == 0 ? (1 / value == 1 / other) : value == +other);
+ : (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
- return value == String(other);
+ return a == String(b);
}
- var isArr = valClass == arrayClass;
+ var isArr = className == arrayClass;
if (!isArr) {
- // exit for functions and DOM nodes
- if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) {
- return false;
- }
// unwrap any `lodash` wrapped values
- var valWrapped = hasOwnProperty.call(value, '__wrapped__'),
- othWrapped = hasOwnProperty.call(other, '__wrapped__');
+ var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
+ bWrapped = hasOwnProperty.call(b, '__wrapped__');
- if (valWrapped || othWrapped) {
- return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, callback, isWhere, stackA, stackB);
+ if (aWrapped || bWrapped) {
+ return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
}
- if (!support.argsObject) {
- valIsArg = isArguments(value);
- othIsArg = isArguments(other);
- }
- var hasValCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'),
- hasOthCtor = !othIsArg && hasOwnProperty.call(other, 'constructor');
-
- if (hasValCtor != hasOthCtor) {
+ // exit for functions and DOM nodes
+ if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {
return false;
}
- if (!hasValCtor) {
- // in older versions of Opera, `arguments` objects have `Array` constructors
- var valCtor = valIsArg ? Object : value.constructor,
- othCtor = othIsArg ? Object : other.constructor;
+ // in older versions of Opera, `arguments` objects have `Array` constructors
+ var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,
+ ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
- // 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;
- }
+ // non `Object` object instances with different constructors are not equal
+ if (ctorA != ctorB &&
+ !(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) &&
+ !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
+ ('constructor' in a && 'constructor' in b)
+ ) {
+ 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)
+ var initedStack = !stackA;
stackA || (stackA = []);
stackB || (stackB = []);
var length = stackA.length;
while (length--) {
- if (stackA[length] == value) {
- return stackB[length] == other;
+ if (stackA[length] == a) {
+ return stackB[length] == b;
}
}
var size = 0;
result = true;
- // add `value` and `other` to the stack of traversed objects
- stackA.push(value);
- stackB.push(other);
+ // add `a` and `b` to the stack of traversed objects
+ stackA.push(a);
+ stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
// compare lengths to determine if a deep comparison is necessary
- length = value.length;
- size = other.length;
+ length = a.length;
+ size = b.length;
result = size == length;
if (result || isWhere) {
// deep compare the contents, ignoring non-numeric properties
while (size--) {
var index = length,
- othValue = other[size];
+ value = b[size];
if (isWhere) {
while (index--) {
- if ((result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB))) {
+ if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
break;
}
}
- if (!result) {
- break;
- }
- } else if (!(result = baseIsEqual(value[size], othValue, callback, isWhere, stackA, stackB))) {
+ } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
break;
}
}
@@ -1733,20 +1604,20 @@
else {
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
- baseForIn(other, function(othValue, key, other) {
- if (hasOwnProperty.call(other, key)) {
+ baseForIn(b, function(value, key, b) {
+ if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
- return (result = hasOwnProperty.call(value, key) && baseIsEqual(value[key], othValue, callback, isWhere, stackA, stackB));
+ return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
}
});
if (result && !isWhere) {
// ensure both objects have the same number of properties
- baseForIn(value, function(valValue, key, value) {
- if (hasOwnProperty.call(value, key)) {
- // `size` will be `-1` if `value` has more properties than `other`
+ baseForIn(a, function(value, key, a) {
+ if (hasOwnProperty.call(a, key)) {
+ // `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
@@ -1760,7 +1631,7 @@
/**
* The base implementation of `_.merge` without argument juggling or support
- * for `this` binding.
+ * for `thisArg` binding.
*
* @private
* @param {Object} object The destination object.
@@ -1770,7 +1641,7 @@
* @param {Array} [stackB=[]] Associates values with source counterparts.
*/
function baseMerge(object, source, callback, stackA, stackB) {
- (isArray(source) ? arrayEach : baseForOwn)(source, function(source, key) {
+ (isArray(source) ? baseEach : baseForOwn)(source, function(source, key) {
var found,
isArr,
result = source,
@@ -1830,7 +1701,7 @@
* @private
* @param {number} min The minimum possible value.
* @param {number} max The maximum possible value.
- * @returns {number} Returns the random number.
+ * @returns {number} Returns a random number.
*/
function baseRandom(min, max) {
return min + floor(nativeRandom() * (max - min + 1));
@@ -1838,13 +1709,13 @@
/**
* The base implementation of `_.uniq` without support for callback shorthands
- * or `this` binding.
+ * or `thisArg` binding.
*
* @private
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function} [callback] The function called per iteration.
- * @returns {Array} Returns the new duplicate-value-free array.
+ * @returns {Array} Returns a duplicate-value-free array.
*/
function baseUniq(array, isSorted, callback) {
var length = array ? array.length : 0;
@@ -1897,37 +1768,15 @@
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 an array that is the composition of partially applied arguments,
* placeholders, and provided arguments into a single array of arguments.
*
* @private
- * @param {Array} partialArgs An array of arguments to prepend to those provided.
+ * @param {Array} partialArg An array of arguments to prepend to those provided.
* @param {Array} partialHolders An array of `partialArgs` placeholder indexes.
* @param {Array|Object} args The provided arguments.
- * @returns {Array} Returns the new array of composed arguments.
+ * @returns {Array} Returns a new array of composed arguments.
*/
function composeArgs(partialArgs, partialHolders, args) {
var holdersLength = partialHolders.length,
@@ -1954,10 +1803,10 @@
* is tailored for `_.partialRight`.
*
* @private
- * @param {Array} partialRightArgs An array of arguments to append to those provided.
+ * @param {Array} partialRightArg An array of arguments to append to those provided.
* @param {Array} partialHolders An array of `partialRightArgs` placeholder indexes.
* @param {Array|Object} args The provided arguments.
- * @returns {Array} Returns the new array of composed arguments.
+ * @returns {Array} Returns a new array of composed arguments.
*/
function composeArgsRight(partialRightArgs, partialRightHolders, args) {
var holdersIndex = -1,
@@ -1982,22 +1831,22 @@
}
/**
- * Creates a function that aggregates a collection, creating an accumulator
- * object composed from the results of running each element in the collection
- * through a callback. The given setter function sets the keys and values of
- * the accumulator object. If `initializer` is provided will be used to
- * initialize the accumulator object.
+ * Creates a function that aggregates a collection, creating an object or
+ * array composed from the results of running each element of the collection
+ * through a callback. The given `setter` function sets the keys and values
+ * of the composed object or array.
*
* @private
- * @param {Function} setter The function to set keys and values of the accumulator object.
- * @param {Function} [initializer] The function to initialize the accumulator object.
+ * @param {Function} setter The setter function.
+ * @param {boolean} [retArray=false] A flag to indicate that the aggregator
+ * function should return an array.
* @returns {Function} Returns the new aggregator function.
*/
- function createAggregator(setter, initializer) {
+ function createAggregator(setter, retArray) {
return function(collection, callback, thisArg) {
- var result = initializer ? initializer() : {};
- callback = lodash.createCallback(callback, thisArg, 3);
+ var result = retArray ? [[], []] : {};
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
length = collection.length;
@@ -2020,7 +1869,7 @@
*
* @private
* @param {Array} [array=[]] The array to search.
- * @returns {Object} Returns the new cache object.
+ * @returns {Object} Returns the cache object.
*/
var createCache = Set && function(array) {
var cache = new Set,
@@ -2034,31 +1883,8 @@
};
/**
- * 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 either curries or invokes `func` with an optional
- * `this` binding and partially applied arguments.
+ * Creates a function that, when called, either curries or invokes `func`
+ * with an optional `this` binding and partially applied arguments.
*
* @private
* @param {Function|string} func The function or method name to reference.
@@ -2076,16 +1902,18 @@
* provided to the new function.
* @param {Array} [partialRightArgs] An array of arguments to append to those
* provided to the new function.
+ * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes.
+ * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes.
* @returns {Function} Returns the new function.
*/
- function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) {
+ function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders) {
var isBind = bitmask & BIND_FLAG,
isBindKey = bitmask & BIND_KEY_FLAG,
isPartial = bitmask & PARTIAL_FLAG,
isPartialRight = bitmask & PARTIAL_RIGHT_FLAG;
if (!isBindKey && !isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
if (isPartial && !partialArgs.length) {
bitmask &= ~PARTIAL_FLAG;
@@ -2141,17 +1969,17 @@
data[1] |= bitmask;
return createWrapper.apply(null, data);
}
- if (isPartial) {
- var partialHolders = getHolders(partialArgs);
- }
- if (isPartialRight) {
- var partialRightHolders = getHolders(partialRightArgs);
- }
if (arity == null) {
arity = isBindKey ? 0 : func.length;
+ } else if (arity < 0) {
+ arity = 0;
+ }
+ if (isPartial) {
+ partialHolders = getHolders(partialArgs);
+ }
+ if (isPartialRight) {
+ partialRightHolders = getHolders(partialRightArgs);
}
- arity = nativeMax(arity, 0);
-
// fast path for `_.bind`
data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders];
return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG))
@@ -2160,11 +1988,40 @@
}
/**
- * Finds the indexes of all placeholder elements in `array`.
+ * Creates compiled iteration functions.
+ *
+ * @private
+ * @param {Object} [options] The compile options object.
+ * @param {string} [options.args] A comma separated string of iteration function arguments.
+ * @param {string} [options.init] The string representation of the initial `result` value.
+ * @param {string} [options.loop] Code to execute in the object loop.
+ * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop.
+ * @returns {Function} Returns the compiled function.
+ */
+ function createIterator(options) {
+ options.shadowedProps = shadowedProps;
+ options.support = support;
+
+ // create the function factory
+ var factory = Function(
+ 'errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, ' +
+ 'nonEnumProps, stringClass, stringProto, toString',
+ 'return function(' + options.args + ') {\n' + iteratorTemplate(options) + '\n}'
+ );
+
+ // return the compiled function
+ return factory(
+ errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto,
+ nonEnumProps, stringClass, stringProto, toString
+ );
+ }
+
+ /**
+ * Finds the indexes of all placeholder elements in a given array.
*
* @private
* @param {Array} array The array to inspect.
- * @returns {Array} Returns the new array of placeholder indexes.
+ * @returns {Array} Returns a new array of placeholder indexes.
*/
function getHolders(array) {
var index = -1,
@@ -2181,15 +2038,15 @@
/**
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
- * customized this function returns the custom method, otherwise it returns
+ * customized this method returns the custom method, otherwise it returns
* the `baseIndexOf` function.
*
* @private
* @returns {Function} Returns the "indexOf" function.
*/
function getIndexOf() {
- var result = lodash.indexOf || indexOf;
- return result === indexOf ? baseIndexOf : result;
+ var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
+ return result;
}
/**
@@ -2197,7 +2054,7 @@
*
* @private
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
*/
function isNative(value) {
return typeof value == 'function' && reNative.test(fnToString.call(value));
@@ -2216,9 +2073,10 @@
};
/**
- * A fallback implementation of `_.isPlainObject` which checks if `value`
- * is an object created by the `Object` constructor or has a `[[Prototype]]`
- * of `null`.
+ * A fallback implementation of `isPlainObject` which checks if a given value
+ * is an object created by the `Object` constructor, assuming objects created
+ * by the `Object` constructor have no inherited enumerable properties and that
+ * there are no `Object.prototype` extensions.
*
* @private
* @param {*} value The value to check.
@@ -2228,7 +2086,7 @@
var ctor,
result;
- // avoid non `Object` objects, `arguments` objects, and DOM elements
+ // avoid non Object objects, `arguments` objects, and DOM elements
if (!(value && toString.call(value) == objectClass) ||
(!hasOwnProperty.call(value, 'constructor') &&
(ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) ||
@@ -2255,36 +2113,67 @@
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`.
+ * Checks if `value` is an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+ * @example
+ *
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ function isArguments(value) {
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
+ toString.call(value) == argsClass || false;
+ }
+ // fallback for environments that can't detect `arguments` objects by [[Class]]
+ if (!support.argsClass) {
+ isArguments = function(value) {
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
+ hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false;
+ };
+ }
+
+ /**
+ * The base implementation of `_.forIn` without support for callback
+ * shorthands or `thisArg` binding.
*
* @private
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns the array of property names.
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @returns {Object} Returns `object`.
*/
- function shimKeys(object) {
- var keyIndex,
- index = -1,
- props = keysIn(object),
- length = props.length,
- objLength = length && object.length,
- maxIndex = objLength - 1,
- result = [];
+ var baseForIn = createIterator({
+ 'args': 'object, callback',
+ 'init': 'object',
+ 'loop': 'if (callback(object[key], key, object) === false) {\n return result;\n }',
+ 'useHas': false
+ });
- 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;
- }
+ /**
+ * A fallback implementation of `Object.keys` which produces an array of the
+ * given object's own enumerable property names.
+ *
+ * @private
+ * @type Function
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns an array of property names.
+ */
+ var shimKeys = createIterator({
+ 'args': 'object',
+ 'init': '[]',
+ 'loop': 'result.push(key)',
+ 'useHas': true
+ });
/*--------------------------------------------------------------------------*/
@@ -2296,7 +2185,7 @@
* @memberOf _
* @category Arrays
* @param {Array} array The array to compact.
- * @returns {Array} Returns the new array of filtered values.
+ * @returns {Array} Returns a new array of filtered values.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
@@ -2326,171 +2215,24 @@
* @category Arrays
* @param {Array} array The array to process.
* @param {...Array} [values] The arrays of values to exclude.
- * @returns {Array} Returns the new array of filtered values.
+ * @returns {Array} Returns a 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, true, true, ++index));
+ function difference(array) {
+ return baseDifference(array, baseFlatten(arguments, true, true, 1));
}
- /**
- * Creates a slice of `array` with `n` elements dropped from the beginning.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to drop.
- * @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]
- */
- var drop = rest;
-
- /**
- * Creates a slice of `array` with `n` elements dropped from the end.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to drop.
- * @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]
- */
- var dropRight = initial;
-
- /**
- * Creates a slice of `array` excluding elements dropped from the end.
- * Elements will be 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 will return the property value of the given element.
- *
- * If an object is provided for `predicate` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=identity] The function called
- * per element.
- * @returns {Array} Returns the slice of `array`.
- * @example
- *
- * _.dropRightWhile([1, 2, 3], function(num) {
- * return num > 1;
- * });
- * // => [1]
- *
- * var characters = [
- * { 'name': 'barney', 'employer': 'slate' },
- * { 'name': 'fred', 'employer': 'slate', 'blocked': true },
- * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.pluck(_.dropRightWhile(characters, 'blocked'), 'name');
- * // => ['barney']
- *
- * // using "_.where" callback shorthand
- * _.pluck(_.dropRightWhile(characters, { 'employer': 'na' }), 'name');
- * // => ['barney', 'fred']
- */
- var dropRightWhile = initial;
-
- /**
- * Creates a slice of `array` excluding elements dropped from the beginning.
- * Elements will be 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 will return the property value of the given element.
- *
- * If an object is provided for `predicate` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=identity] The function called
- * per element.
- * @returns {Array} Returns the slice of `array`.
- * @example
- *
- * _.dropWhile([1, 2, 3], function(num) {
- * return num < 3;
- * });
- * // => [3]
- *
- * var characters = [
- * { 'name': 'barney', 'employer': 'slate', 'blocked': true },
- * { 'name': 'fred', 'employer': 'slate' },
- * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.pluck(_.dropWhile(characters, 'blocked'), 'name');
- * // => ['fred', 'pebbles']
- *
- * // using "_.where" callback shorthand
- * _.pluck(_.dropWhile(characters, { 'employer': 'slate' }), 'name');
- * // => ['pebbles']
- */
- var dropWhile = rest;
-
/**
* 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.
+ * element that passes the callback check, instead of the element itself.
*
- * If a property name is provided for `predicate` the created "_.pluck" style
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -2498,10 +2240,10 @@
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
@@ -2524,13 +2266,13 @@
* _.findIndex(characters, 'blocked');
* // => 1
*/
- function findIndex(array, predicate, thisArg) {
+ function findIndex(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0;
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length) {
- if (predicate(array[index], index, array)) {
+ if (callback(array[index], index, array)) {
return index;
}
}
@@ -2539,12 +2281,12 @@
/**
* This method is like `_.findIndex` except that it iterates over elements
- * of a collection from right to left.
+ * of a `collection` from right to left.
*
- * If a property name is provided for `predicate` the created "_.pluck" style
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -2552,10 +2294,10 @@
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
@@ -2578,12 +2320,12 @@
* _.findLastIndex(characters, 'blocked');
* // => 2
*/
- function findLastIndex(array, predicate, thisArg) {
+ function findLastIndex(array, callback, thisArg) {
var length = array ? array.length : 0;
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
while (length--) {
- if (predicate(array[length], length, array)) {
+ if (callback(array[length], length, array)) {
return length;
}
}
@@ -2591,47 +2333,80 @@
}
/**
- * Gets the first element of `array`.
+ * Gets the first element or first `n` elements of an array. If a callback
+ * is provided elements at the beginning of the array are returned as long
+ * as the callback returns truey. The callback is bound to `thisArg` and
+ * invoked with three arguments; (value, index, array).
*
- * Note: The `n` and `predicate` arguments are deprecated; replace with
- * `_.take` and `_.takeWhile` respectively.
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
- * @alias head
+ * @alias head, take
* @category Arrays
* @param {Array} array The array to query.
- * @returns {*} Returns the first element of `array`.
+ * @param {Function|Object|number|string} [callback] The function called
+ * per element or the number of elements to return. If a property name or
+ * object is provided it will be used to create a "_.pluck" or "_.where"
+ * style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the first element(s) of `array`.
* @example
*
* _.first([1, 2, 3]);
* // => 1
*
- * _.first([]);
- * // => undefined
+ * // returns the first two elements
+ * _.first([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * // returns elements from the beginning until the callback result is falsey
+ * _.first([1, 2, 3], function(num) {
+ * return num < 3;
+ * });
+ * // => [1, 2]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'employer': 'slate', 'blocked': true },
+ * { 'name': 'fred', 'employer': 'slate' },
+ * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.first(characters, 'blocked');
+ * // => [{ 'name': 'barney', 'employer': 'slate', 'blocked': true }]
+ *
+ * // using "_.where" callback shorthand
+ * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
+ * // => ['barney', 'fred']
*/
- function first(array, predicate, thisArg) {
- if (typeof predicate != 'number' && predicate != null) {
+ function first(array, callback, thisArg) {
+ if (typeof callback != 'number' && callback != null) {
var index = -1,
length = array ? array.length : 0,
n = 0;
- predicate = lodash.createCallback(predicate, thisArg, 3);
- while (++index < length && predicate(array[index], index, array)) {
+ callback = lodash.createCallback(callback, thisArg, 3);
+ while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
- n = predicate;
+ n = callback;
if (n == null || thisArg) {
return array ? array[0] : undefined;
}
}
- return slice(array, 0, n < 0 ? 0 : n);
+ return slice(array, 0, n > 0 ? n : 0);
}
/**
* Flattens a nested array (the nesting can be to any depth). If `isShallow`
- * is truthy, the array will only be flattened a single level. If a callback
+ * is truey, the array will only be flattened a single level. If a callback
* is provided each element of the array is passed through the callback before
* flattening. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
@@ -2648,11 +2423,11 @@
* @category Arrays
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
- * @param {Function|Object|string} [callback] The function called per iteration.
- * If a property name or object is provided it will be used to create a "_.pluck"
- * or "_.where" style callback respectively.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns the new flattened array.
+ * @returns {Array} Returns a new flattened array.
* @example
*
* _.flatten([1, [2], [3, [[4]]]]);
@@ -2706,7 +2481,7 @@
* @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`.
+ * @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
@@ -2723,7 +2498,7 @@
function indexOf(array, value, fromIndex) {
var length = array ? array.length : 0;
if (typeof fromIndex == 'number') {
- fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
+ fromIndex = fromIndex < 0 ? nativeMax(0, length + fromIndex) : (fromIndex || 0);
} else if (fromIndex) {
var index = sortedIndex(array, value);
return (length && array[index] === value) ? index : -1;
@@ -2732,37 +2507,73 @@
}
/**
- * Gets all but the last element of `array`.
+ * Gets all but the last element or last `n` elements of an array. If a
+ * callback is provided elements at the end of the array are excluded from
+ * the result as long as the callback returns truey. The callback is bound
+ * to `thisArg` and invoked with three arguments; (value, index, array).
*
- * Note: The `n` and `predicate` arguments are deprecated; replace with
- * `_.dropRight` and `_.dropRightWhile` respectively.
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
- * @returns {Array} Returns the slice of `array`.
+ * @param {Function|Object|number|string} [callback=1] The function called
+ * per element or the number of elements to exclude. If a property name or
+ * object is provided it will be used to create a "_.pluck" or "_.where"
+ * style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a slice of `array`.
* @example
*
* _.initial([1, 2, 3]);
* // => [1, 2]
+ *
+ * // excludes the last two elements
+ * _.initial([1, 2, 3], 2);
+ * // => [1]
+ *
+ * // excludes elements from the end until the callback fails
+ * _.initial([1, 2, 3], function(num) {
+ * return num > 1;
+ * });
+ * // => [1]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'employer': 'slate' },
+ * { 'name': 'fred', 'employer': 'slate', 'blocked': true },
+ * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.initial(characters, 'blocked');
+ * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }]
+ *
+ * // using "_.where" callback shorthand
+ * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
+ * // => ['barney', 'fred']
*/
- function initial(array, predicate, thisArg) {
+ function initial(array, callback, thisArg) {
var length = array ? array.length : 0;
- if (typeof predicate != 'number' && predicate != null) {
+ if (typeof callback != 'number' && callback != null) {
var index = length,
n = 0;
- predicate = lodash.createCallback(predicate, thisArg, 3);
- while (index-- && predicate(array[index], index, array)) {
+ callback = lodash.createCallback(callback, thisArg, 3);
+ while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
- n = (predicate == null || thisArg) ? 1 : predicate;
+ n = (callback == null || thisArg) ? 1 : callback;
}
- n = length - (n || 0);
- return slice(array, 0, n < 0 ? 0 : n);
+ n = length - n;
+ return slice(array, 0, n > 0 ? n : 0);
}
/**
@@ -2772,8 +2583,8 @@
* @static
* @memberOf _
* @category Arrays
- * @param {...Array} [arrays] The arrays to inspect.
- * @returns {Array} Returns the new array of shared values.
+ * @param {...Array} [array] The arrays to inspect.
+ * @returns {Array} Returns an array of shared values.
* @example
*
* _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
@@ -2785,37 +2596,36 @@
argsLength = arguments.length,
caches = [],
indexOf = getIndexOf(),
- prereq = createCache && indexOf === baseIndexOf;
+ prereq = createCache && indexOf === baseIndexOf,
+ seen = [];
while (++argsIndex < argsLength) {
var value = arguments[argsIndex];
if (isArray(value) || isArguments(value)) {
args.push(value);
caches.push(prereq && value.length >= 120 &&
- createCache(argsIndex && value));
+ createCache(argsIndex ? args[argsIndex] : seen));
}
}
- argsLength = args.length;
var array = args[0],
index = -1,
length = array ? array.length : 0,
- result = [],
- seen = caches[0];
+ result = [];
outer:
while (++index < length) {
+ var cache = caches[0];
value = array[index];
- if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) {
+
+ if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
argsIndex = argsLength;
+ (cache || seen).push(value);
while (--argsIndex) {
- var cache = caches[argsIndex];
+ cache = caches[argsIndex];
if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
continue outer;
}
}
- if (seen) {
- seen.push(value);
- }
result.push(value);
}
}
@@ -2823,46 +2633,89 @@
}
/**
- * Gets the last element of `array`.
+ * Gets the last element or last `n` elements of an array. If a callback is
+ * provided elements at the end of the array are returned as long as the
+ * callback returns truey. The callback is bound to `thisArg` and invoked
+ * with three arguments; (value, index, array).
*
- * Note: The `n` and `predicate` arguments are deprecated; replace with
- * `_.takeRight` and `_.takeRightWhile` respectively.
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
- * @returns {*} Returns the last element of `array`.
+ * @param {Function|Object|number|string} [callback] The function called
+ * per element or the number of elements to return. If a property name or
+ * object is provided it will be used to create a "_.pluck" or "_.where"
+ * style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the last element(s) of `array`.
* @example
*
* _.last([1, 2, 3]);
* // => 3
+ *
+ * // returns the last two elements
+ * _.last([1, 2, 3], 2);
+ * // => [2, 3]
+ *
+ * // returns elements from the end until the callback fails
+ * _.last([1, 2, 3], function(num) {
+ * return num > 1;
+ * });
+ * // => [2, 3]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'employer': 'slate' },
+ * { 'name': 'fred', 'employer': 'slate', 'blocked': true },
+ * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.pluck(_.last(characters, 'blocked'), 'name');
+ * // => ['fred', 'pebbles']
+ *
+ * // using "_.where" callback shorthand
+ * _.last(characters, { 'employer': 'na' });
+ * // => [{ 'name': 'pebbles', 'employer': 'na', 'blocked': true }]
*/
- function last(array, predicate, thisArg) {
+ function last(array, callback, thisArg) {
var length = array ? array.length : 0;
- if (typeof predicate != 'number' && predicate != null) {
+ if (typeof callback != 'number' && callback != null) {
var index = length,
n = 0;
- predicate = lodash.createCallback(predicate, thisArg, 3);
- while (index-- && predicate(array[index], index, array)) {
+ callback = lodash.createCallback(callback, thisArg, 3);
+ while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
- n = predicate;
+ n = callback;
if (n == null || thisArg) {
return array ? array[length - 1] : undefined;
}
}
- n = length - (n || 0);
- return slice(array, n < 0 ? 0 : n);
+ n = length - n;
+ return slice(array, n > 0 ? n : 0);
}
/**
- * Gets the index at which the last occurrence of `value` is found using
- * strict equality for comparisons, i.e. `===`. If `fromIndex` is negative,
- * it is used as the offset from the end of the collection.
+ * Gets the index at which the last occurrence of `value` is found using strict
+ * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+ * as the offset from the end of the collection.
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
@@ -2870,7 +2723,7 @@
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=array.length-1] The index to search from.
- * @returns {number} Returns the index of the matched value, else `-1`.
+ * @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
@@ -2883,7 +2736,7 @@
function lastIndexOf(array, value, fromIndex) {
var index = array ? array.length : 0;
if (typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? nativeMax(index + fromIndex, 0) : nativeMin(fromIndex || 0, index - 1)) + 1;
+ index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
}
while (index--) {
if (array[index] === value) {
@@ -2897,13 +2750,11 @@
* Removes all provided values from `array` using strict equality for
* comparisons, i.e. `===`.
*
- * Note: Unlike `_.without`, this method mutates `array`.
- *
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
- * @param {...*} [values] The values to remove.
+ * @param {...*} [value] The values to remove.
* @returns {Array} Returns `array`.
* @example
*
@@ -2932,28 +2783,79 @@
}
/**
- * Removes all elements from `array` that the predicate returns truthy for
- * and returns an array of removed elements. The predicate is bound to `thisArg`
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to but not including `end`. If `start` is less than `stop` a
+ * zero-length range is created unless a negative `step` is specified.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns a new range array.
+ * @example
+ *
+ * _.range(4);
+ * // => [0, 1, 2, 3]
+ *
+ * _.range(1, 5);
+ * // => [1, 2, 3, 4]
+ *
+ * _.range(0, 20, 5);
+ * // => [0, 5, 10, 15]
+ *
+ * _.range(0, -4, -1);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.range(0);
+ * // => []
+ */
+ function range(start, end, step) {
+ start = +start || 0;
+ step = typeof step == 'number' ? step : (+step || 1);
+
+ if (end == null) {
+ end = start;
+ start = 0;
+ }
+ // use `Array(length)` so engines like Chakra and V8 avoid slower modes
+ // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+ var index = -1,
+ length = nativeMax(0, ceil((end - start) / (step || 1))),
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * Removes all elements from an array that the callback returns truey for
+ * and returns an array of removed elements. The callback is bound to `thisArg`
* and invoked with three arguments; (value, index, array).
*
- * If a property name is provided for `predicate` the created "_.pluck" style
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
- * Note: Unlike `_.filter`, this method mutates `array`.
- *
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the array of removed elements.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of removed elements.
* @example
*
* var array = [1, 2, 3, 4, 5, 6];
@@ -2965,15 +2867,15 @@
* console.log(evens);
* // => [2, 4, 6]
*/
- function remove(array, predicate, thisArg) {
+ function remove(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0,
result = [];
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length) {
var value = array[index];
- if (predicate(value, index, array)) {
+ if (callback(value, index, array)) {
result.push(value);
splice.call(array, index--, 1);
length--;
@@ -2983,36 +2885,124 @@
}
/**
- * Gets all but the first element of `array`.
- *
- * Note: The `n` and `predicate` arguments are deprecated; replace with
- * `_.drop` and `_.dropWhile` respectively.
+ * Removes elements located at the given indexes and returns an array of
+ * removed elements. A hybrid of "_.remove" and "_.at". Indexes may be
+ * specified as an array of indexes or as individual arguments.
*
* @static
* @memberOf _
- * @alias tail
+ * @category Arrays
+ * @param {Array} array The array to modify.
+ * @param {...(number|number[])} [index] The indexes of `array` to remove
+ * @returns {Array} Returns a new array of removed elements.
+ * @example
+ *
+ * var array = [5, 10, 15, 20, 25, 30];
+ * var evens = _.removeAt(array, [1, 3, 5]);
+ *
+ * console.log(array);
+ * // => [5, 15, 25]
+ *
+ * console.log(evens);
+ * // => [10, 20, 30]
+ *
+ * var greeting = ('good morning').split('');
+ * var vowels = _.removeAt(greeting, 1, 2, 6, 9);
+ *
+ * console.log(greeting.join(''));
+ * // => 'gd mrnng'
+ *
+ * console.log(vowels.join(''));
+ * // => 'oooi'
+ */
+ function removeAt(array, guard) {
+ var args = arguments,
+ index = -1,
+ removals = baseFlatten(args, true, false, 1),
+ length = removals.length;
+
+ // enables use as a callback for functions like `_.map`
+ if (typeof guard == 'number' && args[2] && args[2][guard] === array) {
+ length = 1;
+ } else {
+ removals.sort(baseCompareAscending);
+ }
+ var result = Array(length);
+ while(++index < length) {
+ result[index] = splice.call(array, removals[index] - index, 1)[0];
+ }
+ return result;
+ }
+
+
+ /**
+ * The opposite of `_.initial`; this method gets all but the first element or
+ * first `n` elements of an array. If a callback function is provided elements
+ * at the beginning of the array are excluded from the result as long as the
+ * callback returns truey. The callback is bound to `thisArg` and invoked
+ * with three arguments; (value, index, array).
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
- * @returns {Array} Returns the slice of `array`.
+ * @param {Function|Object|number|string} [callback=1] The function called
+ * per element or the number of elements to exclude. If a property name or
+ * object is provided it will be used to create a "_.pluck" or "_.where"
+ * style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a slice of `array`.
* @example
*
* _.rest([1, 2, 3]);
* // => [2, 3]
+ *
+ * // excludes the first two elements
+ * _.rest([1, 2, 3], 2);
+ * // => [3]
+ *
+ * // excludes elements from the beginning until the callback fails
+ * _.rest([1, 2, 3], function(num) {
+ * return num < 3;
+ * });
+ * // => [3]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'employer': 'slate', 'blocked': true },
+ * { 'name': 'fred', 'employer': 'slate' },
+ * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.pluck(_.rest(characters, 'blocked'), 'name');
+ * // => ['fred', 'pebbles']
+ *
+ * // using "_.where" callback shorthand
+ * _.rest(characters, { 'employer': 'slate' });
+ * // => [{ 'name': 'pebbles', 'employer': 'na', 'blocked': true }]
*/
- function rest(array, predicate, thisArg) {
- if (typeof predicate != 'number' && predicate != null) {
+ function rest(array, callback, thisArg) {
+ if (typeof callback != 'number' && callback != null) {
var index = -1,
length = array ? array.length : 0,
n = 0;
- predicate = lodash.createCallback(predicate, thisArg, 3);
- while (++index < length && predicate(array[index], index, array)) {
+ callback = lodash.createCallback(callback, thisArg, 3);
+ while (++index < length && callback(array[index], index, array)) {
n++;
}
- } else if (predicate == null || thisArg) {
+ } else if (callback == null || thisArg) {
n = 1;
} else {
- n = predicate < 0 ? 0 : predicate;
+ n = callback > 0 ? callback : 0;
}
return slice(array, n);
}
@@ -3029,25 +3019,27 @@
* @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`.
+ * @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
var index = -1,
length = array ? array.length : 0;
- start = typeof start == 'undefined' ? 0 : (+start || 0);
- if (start < 0) {
+ if (typeof start == 'undefined') {
+ start = 0;
+ } else if (start < 0) {
start = nativeMax(length + start, 0);
} else if (start > length) {
start = length;
}
- end = typeof end == 'undefined' ? length : (+end || 0);
- if (end < 0) {
+ if (typeof end == 'undefined') {
+ end = length;
+ } else if (end < 0) {
end = nativeMax(length + end, 0);
} else if (end > length) {
end = length;
}
- length = start > end ? 0 : (end - start);
+ length = end - start || 0;
var result = Array(length);
while (++index < length) {
@@ -3077,7 +3069,7 @@
* @param {*} value The value to evaluate.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
@@ -3087,17 +3079,17 @@
* // => 2
*
* var dict = {
- * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'forty': 40, 'fifty': 50 }
+ * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
* };
*
* // using `callback`
- * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'forty', function(word) {
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return dict.wordToNumber[word];
* });
* // => 2
*
* // using `callback` with `thisArg`
- * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'forty', function(word) {
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return this.wordToNumber[word];
* }, dict);
* // => 2
@@ -3123,144 +3115,6 @@
return low;
}
- /**
- * Creates a slice of `array` with `n` elements taken from the beginning.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to take.
- * @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);
- * // => []
- */
- var take = first;
-
- /**
- * Creates a slice of `array` with `n` elements taken from the end.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to take.
- * @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);
- * // => []
- */
- var takeRight = last;
-
- /**
- * Creates a slice of `array` with elements taken from the end. Elements will
- * be 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 will return the property value of the given element.
- *
- * If an object is provided for `predicate` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=identity] The function called
- * per element.
- * @returns {Array} Returns the slice of `array`.
- * @example
- *
- * _.takeRightWhile([1, 2, 3], function(num) {
- * return num > 1;
- * });
- * // => [2, 3]
- *
- * var characters = [
- * { 'name': 'barney', 'employer': 'slate' },
- * { 'name': 'fred', 'employer': 'slate', 'blocked': true },
- * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.pluck(_.takeRightWhile(characters, 'blocked'), 'name');
- * // => ['fred', 'pebbles']
- *
- * // using "_.where" callback shorthand
- * _.pluck(_.takeRightWhile(characters, { 'employer': 'na' }), 'name');
- * // => ['pebbles']
- */
- var takeRightWhile = last;
-
- /**
- * Creates a slice of `array` with elements taken from the beginning. Elements
- * will be 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 will return the property value of the given element.
- *
- * If an object is provided for `predicate` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=identity] The function called
- * per element.
- * @returns {Array} Returns the slice of `array`.
- * @example
- *
- * _.takeWhile([1, 2, 3], function(num) {
- * return num < 3;
- * });
- * // => [1, 2]
- *
- * var characters = [
- * { 'name': 'barney', 'employer': 'slate', 'blocked': true },
- * { 'name': 'fred', 'employer': 'slate' },
- * { 'name': 'pebbles', 'employer': 'na', 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.pluck(_.takeWhile(characters, 'blocked'), 'name');
- * // => ['barney']
- *
- * // using "_.where" callback shorthand
- * _.pluck(_.takeWhile(characters, { 'employer': 'slate' }), 'name');
- * // => ['barney', 'fred']
- */
- var takeWhile = first;
-
/**
* Creates an array of unique values, in order, of the provided arrays using
* strict equality for comparisons, i.e. `===`.
@@ -3268,8 +3122,8 @@
* @static
* @memberOf _
* @category Arrays
- * @param {...Array} [arrays] The arrays to inspect.
- * @returns {Array} Returns the new array of combined values.
+ * @param {...Array} [array] The arrays to inspect.
+ * @returns {Array} Returns an array of combined values.
* @example
*
* _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
@@ -3281,11 +3135,11 @@
/**
* Creates a duplicate-value-free version of an array using strict equality
- * for comparisons, i.e. `===`. If the array is sorted, providing `true` for
- * `isSorted` will use a faster algorithm. If a callback is provided it will
- * be executed for each value in the array to generate the criterion by which
- * uniqueness is computed. The callback is bound to `thisArg` and invoked with
- * three arguments; (value, index, array).
+ * for comparisons, i.e. `===`. If the array is sorted, providing
+ * `true` for `isSorted` will use a faster algorithm. If a callback is provided
+ * each element of `array` is passed through the callback before uniqueness
+ * is computed. The callback is bound to `thisArg` and invoked with three
+ * arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
@@ -3300,11 +3154,11 @@
* @category Arrays
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
- * @param {Function|Object|string} [callback] The function called per iteration.
- * If a property name or object is provided it will be used to create a "_.pluck"
- * or "_.where" style callback respectively.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns the new duplicate-value-free array.
+ * @returns {Array} Returns a duplicate-value-free array.
* @example
*
* _.uniq([1, 2, 1, 3, 1]);
@@ -3357,27 +3211,26 @@
* @memberOf _
* @category Arrays
* @param {Array} array The array to filter.
- * @param {...*} [values] The values to exclude.
- * @returns {Array} Returns the new array of filtered values.
+ * @param {...*} [value] The values to exclude.
+ * @returns {Array} Returns a new array of filtered values.
* @example
*
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
* // => [2, 3, 4]
*/
- function without() {
- return baseDifference(arguments[0], slice(arguments, 1));
+ 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.
+ * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details.
*
* @static
* @memberOf _
* @category Arrays
- * @param {...Array} [arrays] The arrays to inspect.
- * @returns {Array} Returns the new array of values.
+ * @param {...Array} [array] The arrays to inspect.
+ * @returns {Array} Returns an array of values.
* @example
*
* _.xor([1, 2, 3], [5, 2, 1, 4]);
@@ -3411,8 +3264,8 @@
* @memberOf _
* @alias unzip
* @category Arrays
- * @param {...Array} [arrays] The arrays to process.
- * @returns {Array} Returns the array of grouped elements.
+ * @param {...Array} [array] The arrays to process.
+ * @returns {Array} Returns a new array of grouped elements.
* @example
*
* _.zip(['fred', 'barney'], [30, 40], [true, false]);
@@ -3444,7 +3297,8 @@
* @category Arrays
* @param {Array} keys The array of keys.
* @param {Array} [values=[]] The array of values.
- * @returns {Object} Returns the new object.
+ * @returns {Object} Returns an object composed of the given keys and
+ * corresponding values.
* @example
*
* _.zipObject(['fred', 'barney'], [30, 40]);
@@ -3479,7 +3333,7 @@
* @memberOf _
* @category Chaining
* @param {*} value The value to wrap.
- * @returns {Object} Returns the new wrapper object.
+ * @returns {Object} Returns the wrapper object.
* @example
*
* var characters = [
@@ -3496,7 +3350,9 @@
* // => 'pebbles is 1'
*/
function chain(value) {
- return new lodashWrapper(value, true);
+ value = new lodashWrapper(value);
+ value.__chain__ = true;
+ return value;
}
/**
@@ -3556,12 +3412,12 @@
}
/**
- * Produces the result of coercing the wrapped value to a string.
+ * Produces the `toString` result of the wrapped value.
*
* @name toString
* @memberOf _
* @category Chaining
- * @returns {string} Returns the coerced string value.
+ * @returns {string} Returns the string result.
* @example
*
* _([1, 2, 3]).toString();
@@ -3576,7 +3432,7 @@
*
* @name valueOf
* @memberOf _
- * @alias toJSON, value
+ * @alias value
* @category Chaining
* @returns {*} Returns the wrapped value.
* @example
@@ -3590,6 +3446,7 @@
/*--------------------------------------------------------------------------*/
+
/**
* Creates an array of elements from the specified indexes, or keys, of the
* `collection`. Indexes may be specified as individual arguments or as arrays
@@ -3599,9 +3456,10 @@
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {...(number|number[]|string|string[])} [keys] The keys of elements
- * to pick, specified as individual keys or arrays of keys.
- * @returns {Array} Returns the array of picked elements.
+ * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
+ * to retrieve, specified as individual indexes or arrays of indexes.
+ * @returns {Array} Returns a new array of elements corresponding to the
+ * provided indexes.
* @example
*
* _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
@@ -3610,11 +3468,17 @@
* _.at(['fred', 'barney', 'pebbles'], 0, 2);
* // => ['fred', 'pebbles']
*/
- function at(collection) {
- var index = -1,
- props = baseFlatten(arguments, true, false, 1),
- length = props.length;
+ function at(collection, guard) {
+ var args = arguments,
+ index = -1,
+ props = baseFlatten(args, true, false, 1),
+ length = props.length,
+ type = typeof guard;
+ // enables use as a callback for functions like `_.map`
+ if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) {
+ length = 1;
+ }
if (support.unindexedChars && isString(collection)) {
collection = collection.split('');
}
@@ -3634,10 +3498,10 @@
* @memberOf _
* @alias include
* @category Collections
- * @param {Array|Object|string} collection The collection to search.
+ * @param {Array|Object|string} collection The collection to iterate over.
* @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`.
+ * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
* @example
*
* _.contains([1, 2, 3], 1);
@@ -3654,25 +3518,31 @@
*/
function contains(collection, target, fromIndex) {
var length = collection ? collection.length : 0;
- if (!(typeof length == 'number' && length > -1 && length <= maxSafeInteger)) {
- collection = values(collection);
- length = collection.length;
- }
- if (typeof fromIndex == 'number') {
- fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
- } else {
- fromIndex = 0;
- }
- if (typeof collection == 'string' || !isArray(collection) && isString(collection)) {
+ fromIndex = typeof fromIndex == 'number' ? fromIndex : 0;
+
+ if (typeof length == 'number') {
if (fromIndex >= length) {
return false;
}
- return nativeContains
- ? nativeContains.call(collection, target, fromIndex)
- : collection.indexOf(target, fromIndex) > -1;
+ if (typeof collection == 'string' || !isArray(collection) && isString(collection)) {
+ return nativeContains
+ ? nativeContains.call(collection, target, fromIndex)
+ : collection.indexOf(target, fromIndex) > -1;
+ }
+ var indexOf = getIndexOf();
+ fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+ return indexOf(collection, target, fromIndex) > -1;
}
- var indexOf = getIndexOf();
- return indexOf(collection, target, fromIndex) > -1;
+ var index = -1,
+ result = false;
+
+ baseEach(collection, function(value) {
+ if (++index >= fromIndex) {
+ return !(result = value === target);
+ }
+ });
+
+ return result;
}
/**
@@ -3695,7 +3565,7 @@
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
@@ -3714,14 +3584,14 @@
});
/**
- * Checks if the predicate returns truthy for **all** elements of a collection.
- * The predicate is bound to `thisArg` and invoked with three arguments;
- * (value, index|key, collection).
+ * Checks if the callback returns truey value for **all** elements of a
+ * collection. The callback 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
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -3730,11 +3600,11 @@
* @alias all
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be 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,
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {boolean} Returns `true` if all elements passed the callback check,
* else `false`.
* @example
*
@@ -3754,36 +3624,36 @@
* _.every(characters, { 'age': 36 });
* // => false
*/
- function every(collection, predicate, thisArg) {
+ function every(collection, callback, thisArg) {
var result = true;
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
- if (!predicate(collection[index], index, collection)) {
+ if (!callback(collection[index], index, collection)) {
return false;
}
}
} else {
baseEach(collection, function(value, index, collection) {
- return (result = !!predicate(value, index, collection));
+ return (result = !!callback(value, index, collection));
});
}
return result;
}
/**
- * Iterates over elements of a collection returning an array of all elements
- * the predicate returns truthy for. The predicate is bound to `thisArg` and
+ * Iterates over elements of a collection, returning an array of all elements
+ * the callback returns truey for. The callback 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
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -3792,11 +3662,11 @@
* @alias select
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the new filtered array.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of elements that passed the callback check.
* @example
*
* var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; });
@@ -3815,23 +3685,23 @@
* _.filter(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36 }]
*/
- function filter(collection, predicate, thisArg) {
+ function filter(collection, callback, thisArg) {
var result = [];
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
- if (predicate(value, index, collection)) {
+ if (callback(value, index, collection)) {
result.push(value);
}
}
} else {
baseEach(collection, function(value, index, collection) {
- if (predicate(value, index, collection)) {
+ if (callback(value, index, collection)) {
result.push(value);
}
});
@@ -3841,26 +3711,26 @@
/**
* Iterates over elements of a collection, returning the first element that
- * the predicate returns truthy for. The predicate is bound to `thisArg` and
+ * the callback returns truey for. The callback 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
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
- * @alias detect
+ * @alias detect, findWhere
* @category Collections
- * @param {Array|Object|string} collection The collection to search.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {*} Returns the matched element, else `undefined`.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the found element, else `undefined`.
* @example
*
* var characters = [
@@ -3882,28 +3752,43 @@
* _.find(characters, 'blocked');
* // => { 'name': 'fred', 'age': 40, 'blocked': true }
*/
- function find(collection, predicate, thisArg) {
+ function find(collection, callback, thisArg) {
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
- var index = findIndex(collection, predicate, thisArg);
- return index > -1 ? collection[index] : undefined;
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ var value = collection[index];
+ if (callback(value, index, collection)) {
+ return value;
+ }
+ }
+ } else {
+ var result;
+ baseEach(collection, function(value, index, collection) {
+ if (callback(value, index, collection)) {
+ result = value;
+ return false;
+ }
+ });
+ return result;
}
- predicate = lodash.createCallback(predicate, thisArg, 3);
- return baseFind(collection, predicate, baseEach);
}
/**
- * This method is like `_.find` except that it iterates over elements of a
- * collection from right to left.
+ * This method is like `_.find` except that it iterates over elements
+ * of a `collection` from right to left.
*
* @static
* @memberOf _
* @category Collections
- * @param {Array|Object|string} collection The collection to search.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {*} Returns the matched element, else `undefined`.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the found element, else `undefined`.
* @example
*
* _.findLast([1, 2, 3, 4], function(num) {
@@ -3911,41 +3796,21 @@
* });
* // => 3
*/
- function findLast(collection, predicate, thisArg) {
- predicate = lodash.createCallback(predicate, thisArg, 3);
- return baseFind(collection, predicate, baseEachRight);
+ function findLast(collection, callback, thisArg) {
+ var result;
+
+ callback = lodash.createCallback(callback, thisArg, 3);
+ baseEachRight(collection, function(value, index, collection) {
+ if (callback(value, index, collection)) {
+ result = value;
+ return false;
+ }
+ });
+ return result;
}
/**
- * 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 Collections
- * @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 characters = [
- * { 'name': 'barney', 'age': 36, 'employer': 'slate' },
- * { 'name': 'fred', 'age': 40, 'employer': 'slate' }
- * ];
- *
- * _.findWhere(characters, { 'employer': 'slate' });
- * // => { 'name': 'barney', 'age': 36, 'employer': 'slate' }
- *
- * _.findWhere(characters, { 'age': 40 });
- * // => { 'name': 'fred', 'age': 40, 'employer': 'slate' }
- */
- function findWhere(collection, source) {
- return find(collection, matches(source));
- }
-
- /**
- * Iterates over elements of a collection executing the callback for each
+ * Iterates over elements of a collection, executing the callback for each
* element. The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection). Callbacks may exit iteration early by
* explicitly returning `false`.
@@ -3971,14 +3836,24 @@
* // => logs each number and returns the object (property order is not guaranteed across environments)
*/
function forEach(collection, callback, thisArg) {
- return (callback && typeof thisArg == 'undefined' && isArray(collection))
- ? arrayEach(collection, callback)
- : baseEach(collection, baseCreateCallback(callback, thisArg, 3));
+ if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ if (callback(collection[index], index, collection) === false) {
+ break;
+ }
+ }
+ } else {
+ baseEach(collection, baseCreateCallback(callback, thisArg, 3));
+ }
+ return collection;
}
/**
- * This method is like `_.forEach` except that it iterates over elements of
- * a collection from right to left.
+ * This method is like `_.forEach` except that it iterates over elements
+ * of a `collection` from right to left.
*
* @static
* @memberOf _
@@ -3994,9 +3869,17 @@
* // => logs each number from right to left and returns '3,2,1'
*/
function forEachRight(collection, callback, thisArg) {
- return (callback && typeof thisArg == 'undefined' && isArray(collection))
- ? arrayEachRight(collection, callback)
- : baseEachRight(collection, baseCreateCallback(callback, thisArg, 3));
+ if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+ var length = collection.length;
+ while (length--) {
+ if (callback(collection[length], length, collection) === false) {
+ break;
+ }
+ }
+ } else {
+ baseEachRight(collection, baseCreateCallback(callback, thisArg, 3));
+ }
+ return collection;
}
/**
@@ -4019,7 +3902,7 @@
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
@@ -4062,23 +3945,23 @@
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
- * var keyData = [
+ * var keys = [
* { 'dir': 'left', 'code': 97 },
* { 'dir': 'right', 'code': 100 }
* ];
*
- * _.indexBy(keyData, 'dir');
+ * _.indexBy(keys, 'dir');
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
*
- * _.indexBy(keyData, function(object) { return String.fromCharCode(object.code); });
+ * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*
- * _.indexBy(keyData, function(object) { return this.fromCharCode(object.code); }, String);
+ * _.indexBy(keys, function(key) { return this.fromCharCode(key.code); }, String);
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*/
var indexBy = createAggregator(function(result, value, key) {
@@ -4086,10 +3969,10 @@
});
/**
- * Invokes the method named by `methodName` on each element in the collection
+ * Invokes the method named by `methodName` on each element in the `collection`
* returning an array of the results of each invoked method. Additional arguments
* will be provided to each invoked method. If `methodName` is a function it
- * will be invoked for, and `this` bound to, each element in the collection.
+ * will be invoked for, and `this` bound to, each element in the `collection`.
*
* @static
* @memberOf _
@@ -4098,7 +3981,7 @@
* @param {Function|string} methodName The name of the method to invoke or
* the function invoked per iteration.
* @param {...*} [args] Arguments to invoke the method with.
- * @returns {Array} Returns the array of results.
+ * @returns {Array} Returns a new array of the results of each invoked method.
* @example
*
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
@@ -4108,16 +3991,22 @@
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
- var args = slice(arguments, 2),
- index = -1,
+ var index = -1,
isFunc = typeof methodName == 'function',
- length = collection && collection.length,
- result = Array(length < 0 ? 0 : length >>> 0);
+ length = collection ? collection.length : 0,
+ result = Array(typeof length == 'number' ? length : 0);
- baseEach(collection, function(value) {
- var func = isFunc ? methodName : (value != null && value[methodName]);
- result[++index] = func ? func.apply(value, args) : undefined;
- });
+ if (arguments.length < 3 && isArray(collection)) {
+ while (++index < length) {
+ var value = collection[index];
+ result[index] = isFunc ? methodName.call(value) : value[methodName]();
+ }
+ } else {
+ var args = slice(arguments, 2);
+ baseEach(collection, function(value) {
+ result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+ });
+ }
return result;
}
@@ -4140,9 +4029,9 @@
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns the new mapped array.
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* _.map([1, 2, 3], function(num) { return num * 3; });
@@ -4161,17 +4050,20 @@
* // => ['barney', 'fred']
*/
function map(collection, callback, thisArg) {
- callback = lodash.createCallback(callback, thisArg, 3);
-
- if (isArray(collection)) {
- return arrayMap(collection, callback, thisArg);
- }
var index = -1,
- result = [];
+ length = collection ? collection.length : 0,
+ result = Array(typeof length == 'number' ? length : 0);
- baseEach(collection, function(value, key, collection) {
- result[++index] = callback(value, key, collection);
- });
+ callback = lodash.createCallback(callback, thisArg, 3);
+ if (isArray(collection)) {
+ while (++index < length) {
+ result[index] = callback(collection[index], index, collection);
+ }
+ } else {
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = callback(value, key, collection);
+ });
+ }
return result;
}
@@ -4193,9 +4085,9 @@
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback] The function called per iteration.
- * If a property name or object is provided it will be used to create a "_.pluck"
- * or "_.where" style callback respectively.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the maximum value.
* @example
@@ -4203,9 +4095,6 @@
* _.max([4, 2, 8, 6]);
* // => 8
*
- * _.max([]);
- * // => -Infinity
- *
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
@@ -4244,7 +4133,7 @@
baseEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
- if (current > computed || (current === -Infinity && current === result)) {
+ if (current > computed) {
computed = current;
result = value;
}
@@ -4271,9 +4160,9 @@
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback] The function called per iteration.
- * If a property name or object is provided it will be used to create a "_.pluck"
- * or "_.where" style callback respectively.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the minimum value.
* @example
@@ -4281,9 +4170,6 @@
* _.min([4, 2, 8, 6]);
* // => 2
*
- * _.min([]);
- * // => Infinity
- *
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
@@ -4322,7 +4208,7 @@
baseEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
- if (current < computed || (current === Infinity && current === result)) {
+ if (current < computed) {
computed = current;
result = value;
}
@@ -4333,14 +4219,14 @@
/**
* 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
+ * contains elements the callback returns truey for, while the second of which
+ * contains elements the callback returns falsey for. The callback 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
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -4348,11 +4234,11 @@
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be 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.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of grouped elements.
* @example
*
* _.partition([1, 2, 3], function(num) { return num % 2; });
@@ -4377,17 +4263,18 @@
*/
var partition = createAggregator(function(result, value, key) {
result[key ? 0 : 1].push(value);
- }, function() { return [[], []]; });
+ }, true);
/**
* Retrieves the value of a specified property from all elements in the collection.
*
* @static
* @memberOf _
+ * @type Function
* @category Collections
* @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.
+ * @returns {Array} Returns a new array of property values.
* @example
*
* var characters = [
@@ -4398,9 +4285,7 @@
* _.pluck(characters, 'name');
* // => ['barney', 'fred']
*/
- function pluck(collection, key) {
- return map(collection, property(key));
- }
+ var pluck = map;
/**
* Reduces a collection to a value which is the accumulated result of running
@@ -4434,8 +4319,8 @@
*/
function reduce(collection, callback, accumulator, thisArg) {
var noaccum = arguments.length < 3;
- callback = lodash.createCallback(callback, thisArg, 4);
+ callback = lodash.createCallback(callback, thisArg, 4);
if (isArray(collection)) {
var index = -1,
length = collection.length;
@@ -4457,8 +4342,8 @@
}
/**
- * This method is like `_.reduce` except that it iterates over elements of a
- * collection from right to left.
+ * This method is like `_.reduce` except that it iterates over elements
+ * of a `collection` from right to left.
*
* @static
* @memberOf _
@@ -4471,14 +4356,14 @@
* @returns {*} Returns the accumulated value.
* @example
*
- * var array = [[0, 1], [2, 3], [4, 5]];
- * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []);
+ * var list = [[0, 1], [2, 3], [4, 5]];
+ * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
* // => [4, 5, 2, 3, 0, 1]
*/
function reduceRight(collection, callback, accumulator, thisArg) {
var noaccum = arguments.length < 3;
- callback = lodash.createCallback(callback, thisArg, 4);
+ callback = lodash.createCallback(callback, thisArg, 4);
baseEachRight(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
@@ -4488,13 +4373,13 @@
}
/**
- * The opposite of `_.filter`; this method returns the elements of a collection
- * the predicate does **not** return truthy for.
+ * The opposite of `_.filter`; this method returns the elements of a
+ * collection that the callback does **not** return truey for.
*
- * If a property name is provided for `predicate` the created "_.pluck" style
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -4502,11 +4387,11 @@
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the new filtered array.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of elements that failed the callback check.
* @example
*
* var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; });
@@ -4525,9 +4410,11 @@
* _.reject(characters, { 'age': 36 });
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*/
- function reject(collection, predicate, thisArg) {
- predicate = lodash.createCallback(predicate, thisArg, 3);
- return filter(collection, negate(predicate));
+ function reject(collection, callback, thisArg) {
+ callback = lodash.createCallback(callback, thisArg, 3);
+ return filter(collection, function(value, index, collection) {
+ return !callback(value, index, collection);
+ });
}
/**
@@ -4539,7 +4426,7 @@
* @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).
+ * @returns {*} Returns the random sample(s) of `collection`.
* @example
*
* _.sample([1, 2, 3, 4]);
@@ -4555,24 +4442,22 @@
collection = collection.split('');
}
if (n == null || guard) {
- var length = collection ? collection.length : 0;
- return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
+ return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
}
var result = shuffle(collection);
- result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length);
+ result.length = nativeMin(nativeMax(0, n), 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.
+ * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) for more details.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to shuffle.
- * @returns {Array} Returns the new shuffled array.
+ * @returns {Array} Returns a new shuffled collection.
* @example
*
* _.shuffle([1, 2, 3, 4]);
@@ -4580,19 +4465,20 @@
*/
function shuffle(collection) {
var index = -1,
- length = collection && collection.length,
- result = Array(length < 0 ? 0 : length >>> 0);
+ length = collection ? collection.length : 0,
+ result = Array(typeof length == 'number' ? length : 0);
baseEach(collection, function(value) {
var rand = baseRandom(0, ++index);
result[index] = result[rand];
result[rand] = value;
});
+
return result;
}
/**
- * Gets the size of the collection by returning `collection.length` for arrays
+ * Gets the size of the `collection` by returning `collection.length` for arrays
* and array-like objects or the number of own enumerable properties for objects.
*
* @static
@@ -4613,21 +4499,19 @@
*/
function size(collection) {
var length = collection ? collection.length : 0;
- return (typeof length == 'number' && length > -1 && length <= maxSafeInteger)
- ? length
- : keys(collection).length;
+ return typeof length == 'number' ? length : keys(collection).length;
}
/**
- * Checks if the predicate returns truthy for **any** element of a 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).
+ * Checks if the callback returns a truey value for **any** element of a
+ * collection. The function returns as soon as it finds a passing value and
+ * does not iterate over the entire collection. The callback 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
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -4636,11 +4520,11 @@
* @alias any
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=identity] The function called
+ * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be 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,
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {boolean} Returns `true` if any element passed the callback check,
* else `false`.
* @example
*
@@ -4660,22 +4544,22 @@
* _.some(characters, { 'age': 1 });
* // => false
*/
- function some(collection, predicate, thisArg) {
+ function some(collection, callback, thisArg) {
var result;
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
- if (predicate(collection[index], index, collection)) {
+ if (callback(collection[index], index, collection)) {
return true;
}
}
} else {
baseEach(collection, function(value, index, collection) {
- return !(result = predicate(value, index, collection));
+ return !(result = callback(value, index, collection));
});
}
return !!result;
@@ -4702,11 +4586,11 @@
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
- * @param {Array|Function|Object|string} [callback=identity] The function
- * called per iteration. If a property name or object is provided it will
- * be used to create a "_.pluck" or "_.where" style callback respectively.
+ * @param {Array|Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns the new sorted array.
+ * @returns {Array} Returns a new array of sorted elements.
* @example
*
* _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
@@ -4732,9 +4616,9 @@
*/
function sortBy(collection, callback, thisArg) {
var index = -1,
- length = collection && collection.length,
multi = callback && isArray(callback),
- result = Array(length < 0 ? 0 : length >>> 0);
+ length = collection ? collection.length : 0,
+ result = Array(typeof length == 'number' ? length : 0);
if (!multi) {
callback = lodash.createCallback(callback, thisArg, 3);
@@ -4762,7 +4646,7 @@
}
/**
- * Converts `collection` to an array.
+ * Converts the `collection` to an array.
*
* @static
* @memberOf _
@@ -4775,8 +4659,7 @@
* // => [2, 3, 4]
*/
function toArray(collection) {
- var length = collection && collection.length;
- if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
+ if (collection && typeof collection.length == 'number') {
return (support.unindexedChars && isString(collection))
? collection.split('')
: slice(collection);
@@ -4786,39 +4669,35 @@
/**
* Performs a deep comparison between each element in `collection` and the
- * source object, returning an array of all elements that have equivalent
+ * `source` object, returning an array of all elements that have equivalent
* property values.
*
* @static
* @memberOf _
+ * @type Function
* @category Collections
- * @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.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Object} source The object of property values to filter by.
+ * @returns {Array} Returns a new array of elements that have the given properties.
* @example
*
* var characters = [
- * { 'name': 'barney', 'age': 36, 'employer': 'slate', 'pets': ['hoppy'] },
- * { 'name': 'fred', 'age': 40, 'employer': 'slate', 'pets': ['baby puss', 'dino'] }
+ * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
+ * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
- * _.pluck(_.where(characters, { 'age': 36 }), 'name');
- * // => ['barney']
+ * _.where(characters, { 'age': 36 });
+ * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
*
- * _.pluck(_.where(characters, { 'pets': ['dino'] }), 'name');
- * // => ['fred']
- *
- * _.pluck(_.where(characters, { 'employer': 'slate' }), 'name');
- * // => ['barney', 'fred']
+ * _.where(characters, { 'pets': ['dino'] });
+ * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
*/
- function where(collection, source) {
- return filter(collection, matches(source));
- }
+ var where = filter;
/*--------------------------------------------------------------------------*/
/**
- * Creates a function that executes `func`, with the `this` binding and
+ * Creates a function that executes `func`, with the `this` binding and
* arguments of the created function, only after being called `n` times.
*
* @static
@@ -4843,9 +4722,8 @@
*/
function after(n, func) {
if (!isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
- n = nativeIsFinite(n = +n) ? n : 0;
return function() {
if (--n < 1) {
return func.apply(this, arguments);
@@ -4854,9 +4732,9 @@
}
/**
- * 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.
+ * Creates a function that, when called, 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.
@@ -4903,8 +4781,8 @@
* @memberOf _
* @category Functions
* @param {Object} object The object to bind and assign the bound methods to.
- * @param {...string} [methodNames] The object method names to bind, specified
- * as individual method names or arrays of method names.
+ * @param {...string} [methodName] The object method names to
+ * bind, specified as individual method names or arrays of method names.
* @returns {Object} Returns `object`.
* @example
*
@@ -4930,10 +4808,10 @@
}
/**
- * 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 will be redefined or don't yet exist.
+ * Creates a function that, when called, 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 will be redefined or don't yet exist.
* See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern)
* for more details.
*
@@ -4979,7 +4857,7 @@
* @static
* @memberOf _
* @category Functions
- * @param {...Function} [funcs] Functions to compose.
+ * @param {...Function} [func] Functions to compose.
* @returns {Function} Returns the new composed function.
* @example
*
@@ -5007,7 +4885,7 @@
while (length--) {
if (!isFunction(funcs[length])) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
}
return function() {
@@ -5065,7 +4943,7 @@
* the leading and/or trailing edge of the `wait` timeout. Subsequent calls
* to the debounced function will return the result of the last `func` call.
*
- * Note: If `leading` and `trailing` options are `true`, `func` will be called
+ * Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the debounced function is
* invoked more than once during the `wait` timeout.
*
@@ -5110,15 +4988,15 @@
trailing = true;
if (!isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
- wait = wait < 0 ? 0 : wait;
+ wait = nativeMax(0, wait) || 0;
if (options === true) {
var leading = true;
trailing = false;
} else if (isObject(options)) {
leading = options.leading;
- maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0);
+ maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
trailing = 'trailing' in options ? options.trailing : trailing;
}
var delayed = function() {
@@ -5215,7 +5093,7 @@
*/
function defer(func) {
if (!isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
var args = slice(arguments, 1);
return setTimeout(function() { func.apply(undefined, args); }, 1);
@@ -5239,7 +5117,7 @@
*/
function delay(func, wait) {
if (!isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
var args = slice(arguments, 2);
return setTimeout(function() { func.apply(undefined, args); }, wait);
@@ -5257,7 +5135,7 @@
* @memberOf _
* @category Functions
* @param {Function} func The function to have its output memoized.
- * @param {Function} [resolver] The function to resolve the cache key.
+ * @param {Function} [resolver] A function used to resolve the cache key.
* @returns {Function} Returns the new memoizing function.
* @example
*
@@ -5283,8 +5161,8 @@
* // => { 'name': 'penelope', 'age': 1 }
*/
function memoize(func, resolver) {
- if (!isFunction(func) || (resolver && !isFunction(resolver))) {
- throw new TypeError(funcErrorText);
+ if (!isFunction(func)) {
+ throw new TypeError;
}
var memoized = function() {
var cache = memoized.cache,
@@ -5298,34 +5176,6 @@
return memoized;
}
- /**
- * Creates a function that negates the result of the predicate `func`. The
- * `func` function is executed with the `this` binding and arguments of the
- * created function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} predicate The predicate to negate.
- * @returns {Function} Returns the new function.
- * @example
- *
- * function isEven(num) {
- * return num % 2 == 0;
- * }
- *
- * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
- * // => [1, 3, 5]
- */
- function negate(predicate) {
- if (!isFunction(predicate)) {
- throw new TypeError(funcErrorText);
- }
- return function() {
- return !predicate.apply(this, arguments);
- };
- }
-
/**
* Creates a function that is restricted to execute `func` once. Repeat calls to
* the function will return the value of the first call. The `func` is executed
@@ -5348,7 +5198,7 @@
result;
if (!isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
return function() {
if (ran) {
@@ -5364,9 +5214,9 @@
}
/**
- * Creates a function that invokes `func` with any additional `partial` arguments
- * prepended to those provided to the new function. This method is similar to
- * `_.bind` except it does **not** alter the `this` binding.
+ * Creates a function that, when called, invokes `func` with any additional
+ * `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.
@@ -5409,15 +5259,20 @@
* @returns {Function} Returns the new partially applied function.
* @example
*
- * var defaultsDeep = _.partialRight(_.merge, function deep(value, other) {
- * return _.merge(value, other, deep);
- * });
+ * var defaultsDeep = _.partialRight(_.merge, _.defaults);
*
- * var object = { 'a': { 'b': { 'c': 1 } } },
- * source = { 'a': { 'b': { 'c': 2, 'd': 2 } } };
+ * var options = {
+ * 'variable': 'data',
+ * 'imports': { 'jq': $ }
+ * };
*
- * defaultsDeep(object, source);
- * // => { 'a': { 'b': { 'c': 1, 'd': 2 } } }
+ * defaultsDeep(options, _.templateSettings);
+ *
+ * options.variable
+ * // => 'data'
+ *
+ * options.imports
+ * // => { '_': _, 'jq': $ }
*/
function partialRight(func) {
if (func) {
@@ -5436,7 +5291,7 @@
* of the `wait` timeout. Subsequent calls to the throttled function will
* return the result of the last `func` call.
*
- * Note: If `leading` and `trailing` options are `true`, `func` will be called
+ * Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the throttled function is
* invoked more than once during the `wait` timeout.
*
@@ -5465,16 +5320,16 @@
trailing = true;
if (!isFunction(func)) {
- throw new TypeError(funcErrorText);
+ throw new TypeError;
}
if (options === false) {
leading = false;
} else if (isObject(options)) {
- leading = 'leading' in options ? !!options.leading : leading;
- trailing = 'trailing' in options ? !!options.trailing : trailing;
+ leading = 'leading' in options ? options.leading : leading;
+ trailing = 'trailing' in options ? options.trailing : trailing;
}
debounceOptions.leading = leading;
- debounceOptions.maxWait = +wait;
+ debounceOptions.maxWait = wait;
debounceOptions.trailing = trailing;
return debounce(func, wait, debounceOptions);
@@ -5507,6 +5362,7 @@
/*--------------------------------------------------------------------------*/
+
/**
* Assigns own enumerable properties of source object(s) to the destination
* object. Subsequent sources will overwrite property assignments of previous
@@ -5519,7 +5375,7 @@
* @alias extend
* @category Objects
* @param {Object} object The destination object.
- * @param {...Object} [sources] The source objects.
+ * @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize assigning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
@@ -5528,19 +5384,16 @@
* _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
* // => { 'name': 'fred', 'employer': 'slate' }
*
- * var defaults = _.partialRight(_.assign, function(value, other) {
- * return typeof value == 'undefined' ? other : value;
+ * var defaults = _.partialRight(_.assign, function(a, b) {
+ * return typeof a == 'undefined' ? b : a;
* });
*
* defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
function assign(object, source, guard) {
- var args = arguments;
- if (!object || args.length < 2) {
- return object;
- }
- var argsIndex = 0,
+ var args = arguments,
+ argsIndex = 0,
argsLength = args.length,
type = typeof guard;
@@ -5556,13 +5409,15 @@
}
while (++argsIndex < argsLength) {
source = args[argsIndex];
- var index = -1,
- props = keys(source),
- length = props.length;
+ if (isObject(source)) {
+ var index = -1,
+ props = keys(source),
+ length = props.length;
- while (++index < length) {
- var key = props[index];
- object[key] = callback ? callback(object[key], source[key]) : source[key];
+ while (++index < length) {
+ var key = props[index];
+ object[key] = callback ? callback(object[key], source[key]) : source[key];
+ }
}
}
return object;
@@ -5720,14 +5575,11 @@
* object for all destination properties that resolve to `undefined`. Once a
* property is set, additional defaults of the same property will be ignored.
*
- * Note: See the [documentation example of `_.partialRight`](http://lodash.com/docs#partialRight)
- * for a deep version of this method.
- *
* @static
* @memberOf _
* @category Objects
* @param {Object} object The destination object.
- * @param {...Object} [sources] The source objects.
+ * @param {...Object} [source] The source objects.
* @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
* @returns {Object} Returns the destination object.
* @example
@@ -5735,23 +5587,42 @@
* _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
- function defaults(object) {
- if (!object) {
- return object;
+ function defaults(object, source, guard) {
+ var args = arguments,
+ argsIndex = 0,
+ argsLength = args.length,
+ type = typeof guard;
+
+ // enables use as a callback for functions like `_.reduce`
+ if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) {
+ argsLength = 2;
}
- var args = slice(arguments);
- args.push(assignDefaults);
- return assign.apply(null, args);
+ while (++argsIndex < argsLength) {
+ source = args[argsIndex];
+ if (isObject(source)) {
+ var index = -1,
+ props = keys(source),
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+ if (typeof object[key] == 'undefined') {
+ object[key] = source[key];
+ }
+ }
+ }
+ }
+ return object;
}
/**
* 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.
+ * first element that passes the callback check, instead of the element itself.
*
- * If a property name is provided for `predicate` the created "_.pluck" style
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -5759,11 +5630,11 @@
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
- * @param {Function|Object|string} [predicate=identity] The function called
- * per iteration. If a property name or object is provided it will be 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`.
+ * @param {Function|Object|string} [callback=identity] The function called per
+ * iteration. If a property name or object is provided it will be used to
+ * create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
@@ -5785,19 +5656,27 @@
* _.findKey(characters, 'blocked');
* // => 'fred'
*/
- function findKey(object, predicate, thisArg) {
- predicate = lodash.createCallback(predicate, thisArg, 3);
- return baseFind(object, predicate, baseForOwn, true);
+ function findKey(object, callback, thisArg) {
+ var result;
+
+ callback = lodash.createCallback(callback, thisArg, 3);
+ baseForOwn(object, function(value, key, object) {
+ if (callback(value, key, object)) {
+ result = key;
+ return false;
+ }
+ });
+ return result;
}
/**
- * This method is like `_.findKey` except that it iterates over elements of
- * a collection in the opposite order.
+ * 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
+ * If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
- * If an object is provided for `predicate` the created "_.where" style callback
+ * If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
@@ -5805,11 +5684,11 @@
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
- * @param {Function|Object|string} [predicate=identity] The function called
- * per iteration. If a property name or object is provided it will be 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`.
+ * @param {Function|Object|string} [callback=identity] The function called per
+ * iteration. If a property name or object is provided it will be used to
+ * create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
@@ -5831,19 +5710,28 @@
* _.findLastKey(characters, 'blocked');
* // => 'pebbles'
*/
- function findLastKey(object, predicate, thisArg) {
- predicate = lodash.createCallback(predicate, thisArg, 3);
- return baseFind(object, predicate, baseForOwnRight, true);
+ function findLastKey(object, callback, thisArg) {
+ var result;
+
+ callback = lodash.createCallback(callback, thisArg, 3);
+ baseForOwnRight(object, function(value, key, object) {
+ if (callback(value, key, object)) {
+ result = key;
+ return false;
+ }
+ });
+ return result;
}
/**
- * Iterates over own and inherited enumerable properties of an object executing
- * the callback for each property. The callback is bound to `thisArg` and invoked
- * with three arguments; (value, key, object). Callbacks may exit iteration
- * early by explicitly returning `false`.
+ * Iterates over own and inherited enumerable properties of an object,
+ * executing the callback for each property. The callback is bound to `thisArg`
+ * and invoked with three arguments; (value, key, object). Callbacks may exit
+ * iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
+ * @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
@@ -5856,21 +5744,24 @@
* this.y = 0;
* }
*
- * Shape.prototype.z = 0;
+ * Shape.prototype.move = function(x, y) {
+ * this.x += x;
+ * this.y += y;
+ * };
*
* _.forIn(new Shape, function(value, key) {
* console.log(key);
* });
- * // => logs 'x', 'y', and 'z' (property order is not guaranteed across environments)
+ * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
*/
function forIn(object, callback, thisArg) {
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
- return baseFor(object, callback, keysIn);
+ return baseForIn(object, callback);
}
/**
- * This method is like `_.forIn` except that it iterates over elements of a
- * collection in the opposite order.
+ * This method is like `_.forIn` except that it iterates over elements
+ * of a `collection` in the opposite order.
*
* @static
* @memberOf _
@@ -5886,20 +5777,34 @@
* this.y = 0;
* }
*
- * Shape.prototype.z = 0;
+ * Shape.prototype.move = function(x, y) {
+ * this.x += x;
+ * this.y += y;
+ * };
*
* _.forInRight(new Shape, function(value, key) {
* console.log(key);
* });
- * // => logs 'z', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'z'
+ * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
*/
function forInRight(object, callback, thisArg) {
+ var pairs = [];
+ baseForIn(object, function(value, key) {
+ pairs.push(key, value);
+ });
+
+ var length = pairs.length;
callback = baseCreateCallback(callback, thisArg, 3);
- return baseForRight(object, callback, keysIn);
+ while (length--) {
+ if (callback(pairs[length--], pairs[length], object) === false) {
+ break;
+ }
+ }
+ return object;
}
/**
- * Iterates over own enumerable properties of an object executing the callback
+ * Iterates over own enumerable properties of an object, executing the callback
* for each property. The callback is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by
* explicitly returning `false`.
@@ -5924,8 +5829,8 @@
}
/**
- * This method is like `_.forOwn` except that it iterates over elements of a
- * collection in the opposite order.
+ * This method is like `_.forOwn` except that it iterates over elements
+ * of a `collection` in the opposite order.
*
* @static
* @memberOf _
@@ -5942,8 +5847,17 @@
* // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
*/
function forOwnRight(object, callback, thisArg) {
+ var props = keys(object),
+ length = props.length;
+
callback = baseCreateCallback(callback, thisArg, 3);
- return baseForRight(object, callback, keys);
+ while (length--) {
+ var key = props[length];
+ if (callback(object[key], key, object) === false) {
+ break;
+ }
+ }
+ return object;
}
/**
@@ -5955,7 +5869,7 @@
* @alias methods
* @category Objects
* @param {Object} object The object to inspect.
- * @returns {Array} Returns the new sorted array of property names.
+ * @returns {Array} Returns an array of property names that have function values.
* @example
*
* _.functions(_);
@@ -5963,7 +5877,6 @@
*/
function functions(object) {
var result = [];
-
baseForIn(object, function(value, key) {
if (isFunction(value)) {
result.push(key);
@@ -6002,7 +5915,7 @@
* @category Objects
* @param {Object} object The object to invert.
* @param {boolean} [multiValue=false] Allow multiple values per key.
- * @returns {Object} Returns the new inverted object.
+ * @returns {Object} Returns the created inverted object.
* @example
*
* _.invert({ 'first': 'fred', 'second': 'barney' });
@@ -6040,53 +5953,26 @@
return result;
}
- /**
- * Checks if `value` is an `arguments` object.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @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) {
- return (value && typeof value == 'object' && typeof value.length == 'number' &&
- toString.call(value) == argsClass) || false;
- }
- // fallback for environments without a `[[Class]]` for `arguments` objects
- if (!support.argsClass) {
- isArguments = function(value) {
- return (value && typeof value == 'object' && typeof value.length == 'number' &&
- hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee')) || false;
- };
- }
-
/**
* Checks if `value` is an array.
*
* @static
* @memberOf _
+ * @type Function
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an array, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
* @example
*
- * _.isArray([1, 2, 3]);
- * // => true
- *
* (function() { return _.isArray(arguments); })();
* // => false
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
*/
var isArray = nativeIsArray || function(value) {
- return (value && typeof value == 'object' && typeof value.length == 'number' &&
- toString.call(value) == arrayClass) || false;
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
+ toString.call(value) == arrayClass || false;
};
/**
@@ -6096,38 +5982,32 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a boolean value, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a boolean value, 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;
+ return value === true || value === false ||
+ value && typeof value == 'object' && toString.call(value) == boolClass || false;
}
/**
- * Checks if `value` is a `Date` object.
+ * Checks if `value` is a date.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a date, 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;
+ return value && typeof value == 'object' && toString.call(value) == dateClass || false;
}
/**
@@ -6137,63 +6017,56 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
+ * @returns {boolean} Returns `true` if the `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 : isNode(value))) || false;
+ return value && typeof value == 'object' && value.nodeType === 1 &&
+ (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(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;
+ 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, array-like object, or string with a length greater than `0` or
- * an object with own properties.
+ * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+ * length of `0` and objects with no own enumerable properties are considered
+ * "empty".
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|string} value The value to inspect.
- * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
* @example
*
- * _.isEmpty(null);
- * // => true
- *
- * _.isEmpty(true);
- * // => true
- *
- * _.isEmpty(1);
- * // => true
- *
* _.isEmpty([1, 2, 3]);
* // => false
*
- * _.isEmpty({ 'a': 1 });
- * // => false
+ * _.isEmpty({});
+ * // => true
+ *
+ * _.isEmpty('');
+ * // => true
*/
function isEmpty(value) {
var result = true;
if (!value) {
return result;
}
- var length = value.length;
- if ((length > -1 && length <= maxSafeInteger) &&
- (isArray(value) || isString(value) || isArguments(value) ||
- (typeof value == 'object' && isFunction(value.splice)))) {
+ var className = toString.call(value),
+ length = value.length;
+
+ if ((className == arrayClass || className == stringClass ||
+ (support.argsClass ? className == argsClass : isArguments(value))) ||
+ (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
return !length;
}
baseForOwn(value, function() {
@@ -6204,83 +6077,61 @@
/**
* Performs a deep comparison between two values to determine if they are
- * equivalent. If a callback is provided it will be executed to compare
- * values. If the callback returns `undefined` comparisons will be handled
- * by the method instead. The callback is bound to `thisArg` and invoked
- * with two arguments; (value, other).
- *
- * Note: This method supports comparing arrays, booleans, `Date` objects,
- * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes
- * are **not** supported. A callback may be used to extend support for
- * comparing other values.
+ * equivalent to each other. If a callback is provided it will be executed
+ * to compare values. If the callback returns `undefined` comparisons will
+ * be handled by the method instead. The callback is bound to `thisArg` and
+ * invoked with two arguments; (a, b).
*
* @static
* @memberOf _
* @category Objects
- * @param {*} value The value to compare to `other`.
- * @param {*} other The value to compare to `value`.
+ * @param {*} a The value to compare.
+ * @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'name': 'fred' };
- * var other = { 'name': 'fred' };
+ * var copy = { 'name': 'fred' };
*
- * object == other;
+ * object == copy;
* // => false
*
- * _.isEqual(object, other);
+ * _.isEqual(object, copy);
* // => true
*
* var words = ['hello', 'goodbye'];
* var otherWords = ['hi', 'goodbye'];
*
- * _.isEqual(words, otherWords, function() {
- * return _.every(arguments, _.bind(RegExp.prototype.test, /^h(?:i|ello)$/)) || undefined;
+ * _.isEqual(words, otherWords, function(a, b) {
+ * var reGreet = /^(?:hello|hi)$/i,
+ * aGreet = _.isString(a) && reGreet.test(a),
+ * bGreet = _.isString(b) && reGreet.test(b);
+ *
+ * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
* });
* // => true
*/
- function isEqual(value, other, callback, thisArg) {
+ function isEqual(a, b, callback, thisArg) {
callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2);
if (!callback) {
// exit early for identical values
- if (value === other) {
+ if (a === b) {
// treat `-0` vs. `+0` as not equal
- return value !== 0 || (1 / value == 1 / other);
+ return a !== 0 || (1 / a == 1 / b);
}
- var valType = typeof value,
- othType = typeof other;
+ var type = typeof a,
+ otherType = typeof b;
// exit early for unlike primitive values
- if (value === value && (value == null || other == null ||
- (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) {
+ if (a === a && (a == null || b == null ||
+ (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) {
return false;
}
}
- return baseIsEqual(value, other, callback);
- }
-
- /**
- * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
- * `SyntaxError`, `TypeError`, or `URIError` object.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @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;
+ return baseIsEqual(a, b, callback);
}
/**
@@ -6294,7 +6145,7 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is finite, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
* @example
*
* _.isFinite(-101);
@@ -6323,14 +6174,11 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a function, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
- *
- * _.isFunction(/abc/);
- * // => false
*/
function isFunction(value) {
return typeof value == 'function';
@@ -6343,14 +6191,14 @@
}
/**
- * Checks if `value` is the language type of `Object`.
+ * Checks if `value` is the language type of Object.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
@@ -6363,12 +6211,12 @@
* // => false
*/
function isObject(value) {
- // check if the value is the ECMAScript language type of `Object`
+ // check if the value is the ECMAScript language type of Object
// http://es5.github.io/#x8
// and avoid a V8 bug
// https://code.google.com/p/v8/issues/detail?id=2291
var type = typeof value;
- return type == 'function' || (value && type == 'object') || false;
+ return value && (type == 'function' || type == 'object') || false;
}
/**
@@ -6382,7 +6230,7 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
@@ -6399,7 +6247,7 @@
*/
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)
+ // (perform the [[Class]] check first to avoid errors with some host objects in IE)
return isNumber(value) && value != +value;
}
@@ -6410,13 +6258,13 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
* // => true
*
- * _.isNull(void 0);
+ * _.isNull(undefined);
* // => false
*/
function isNull(value) {
@@ -6424,7 +6272,7 @@
}
/**
- * Checks if `value` is a `Number` primitive or object.
+ * Checks if `value` is a number.
*
* Note: `NaN` is considered a number. See the [ES5 spec](http://es5.github.io/#x8.5)
* for more details.
@@ -6433,30 +6281,20 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a number, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
* @example
*
- * _.isNumber(8.4);
+ * _.isNumber(8.4 * 5);
* // => 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;
+ 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.
+ * Checks if `value` is an object created by the `Object` constructor.
*
* @static
* @memberOf _
@@ -6478,9 +6316,6 @@
*
* _.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))) {
@@ -6495,44 +6330,40 @@
};
/**
- * Checks if `value` is a `RegExp` object.
+ * Checks if `value` is a regular expression.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a regexp object, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
* @example
*
- * _.isRegExp(/abc/);
+ * _.isRegExp(/fred/);
* // => true
- *
- * _.isRegExp('/abc/');
- * // => false
*/
function isRegExp(value) {
- return (isObject(value) && toString.call(value) == regexpClass) || false;
+ var type = typeof value;
+ return value && (type == 'function' || type == 'object') &&
+ toString.call(value) == regexpClass || false;
}
/**
- * Checks if `value` is a `String` primitive or object.
+ * Checks if `value` is a string.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
* @example
*
- * _.isString('abc');
+ * _.isString('fred');
* // => true
- *
- * _.isString(1);
- * // => false
*/
function isString(value) {
return typeof value == 'string' ||
- (value && typeof value == 'object' && toString.call(value) == stringClass) || false;
+ value && typeof value == 'object' && toString.call(value) == stringClass || false;
}
/**
@@ -6542,121 +6373,39 @@
* @memberOf _
* @category Objects
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
* // => true
- *
- * _.isUndefined(null);
- * // => false
*/
function isUndefined(value) {
return typeof value == 'undefined';
}
/**
- * Creates an array of the own enumerable property names of `object`.
+ * Creates an array composed of the own enumerable property names of an object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
- * @returns {Array} Returns the array of property names.
+ * @returns {Array} Returns an array of property names.
* @example
*
- * function Shape() {
- * this.x = 0;
- * this.y = 0;
- * }
- *
- * Shape.prototype.z = 0;
- *
- * _.keys(new Shape);
- * // => ['x', 'y'] (property order is not guaranteed across environments)
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
*/
var keys = !nativeKeys ? shimKeys : function(object) {
- var ctor = object && object.constructor,
- length = object ? object.length : 0;
-
- if ((typeof length == 'number' && length > 0) ||
- (ctor && object === ctor.prototype)) {
- return shimKeys(object);
- }
- return isObject(object) ? nativeKeys(object) : [];
- };
-
- /**
- * Creates an array of the own and inherited enumerable property names of `object`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @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'] (property order is not guaranteed across environments)
- */
- function keysIn(object) {
if (!isObject(object)) {
return [];
}
- 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 && object === ctor.prototype,
- 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);
+ if ((support.enumPrototypes && typeof object == 'function') ||
+ (support.nonEnumArgs && object.length && isArguments(object))) {
+ return shimKeys(object);
}
- 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);
- }
- }
- // Lo-Dash skips the `constructor` property when it infers it's 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.
- 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;
- }
+ return nativeKeys(object);
+ };
/**
* Creates an object with the same keys as `object` and values generated by
@@ -6677,9 +6426,9 @@
* @param {Object} object The object to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback respectively.
+ * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the new mapped object.
+ * @returns {Object} Returns a new object with values of the results of each `callback` execution.
* @example
*
* _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
@@ -6696,8 +6445,8 @@
*/
function mapValues(object, callback, thisArg) {
var result = {};
- callback = lodash.createCallback(callback, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
baseForOwn(object, function(value, key, object) {
result[key] = callback(value, key, object);
});
@@ -6717,7 +6466,7 @@
* @memberOf _
* @category Objects
* @param {Object} object The destination object.
- * @param {...Object} [sources] The source objects.
+ * @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize merging properties.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
@@ -6756,13 +6505,13 @@
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
*/
function merge(object, source, guard) {
+ if (!isObject(object)) {
+ return object;
+ }
var args = arguments,
length = args.length,
type = typeof guard;
- if (!object || length < 2) {
- return object;
- }
// enables use as a callback for functions like `_.reduce`
if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) {
length = 2;
@@ -6773,7 +6522,7 @@
} else if (length > 2 && typeof args[length - 1] == 'function') {
callback = args[--length];
}
- var sources = slice(args, 1, length),
+ var sources = slice(arguments, 1, length),
index = -1,
stackA = [],
stackB = [];
@@ -6787,20 +6536,20 @@
/**
* 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 will be executed for each
- * property of `object` omitting the properties the predicate returns truthy
- * for. The predicate is bound to `thisArg` and invoked with three arguments;
+ * property names. If a callback is provided it will be executed for each
+ * property of `object` omitting the properties the callback returns truey
+ * for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
- * @param {Function|...string|string[]} [predicate] The function called per
+ * @param {Function|...string|string[]} [callback] The function called 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.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns an object without the omitted properties.
* @example
*
* _.omit({ 'name': 'fred', 'age': 40 }, 'age');
@@ -6811,29 +6560,49 @@
* });
* // => { 'name': 'fred' }
*/
- function omit(object, predicate, thisArg) {
- if (typeof predicate == 'function') {
- predicate = lodash.createCallback(predicate, thisArg, 3);
- return pick(object, negate(predicate));
- }
- var omitProps = baseFlatten(arguments, true, false, 1),
- length = omitProps.length;
+ function omit(object, callback, thisArg) {
+ var result = {};
- while (length--) {
- omitProps[length] = String(omitProps[length]);
+ if (typeof callback != 'function') {
+ var omitProps = baseFlatten(arguments, true, false, 1),
+ length = omitProps.length;
+
+ while (length--) {
+ omitProps[length] = String(omitProps[length]);
+ }
+ var props = [];
+ baseForIn(object, function(value, key) {
+ props.push(key);
+ });
+
+ var index = -1;
+ props = baseDifference(props, omitProps);
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+ result[key] = object[key];
+ }
+ } else {
+ callback = lodash.createCallback(callback, thisArg, 3);
+ baseForIn(object, function(value, key, object) {
+ if (!callback(value, key, object)) {
+ result[key] = value;
+ }
+ });
}
- return pick(object, baseDifference(keysIn(object), omitProps));
+ return result;
}
/**
- * Creates a two dimensional array of a given object's key-value pairs,
+ * Creates a two dimensional array of an object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
- * @returns {Array} Returns the new array of key-value pairs.
+ * @returns {Array} Returns new array of key-value pairs.
* @example
*
* _.pairs({ 'barney': 36, 'fred': 40 });
@@ -6855,20 +6624,20 @@
/**
* 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 will be executed for each
- * property of `object` picking the properties the predicate returns truthy
- * for. The predicate is bound to `thisArg` and invoked with three arguments;
+ * property names. If a callback is provided it will be executed for each
+ * property of `object` picking the properties the callback returns truey
+ * for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
- * @param {Function|...string|string[]} [predicate] The function called per
+ * @param {Function|...string|string[]} [callback] The function called 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.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns an object composed of the picked properties.
* @example
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
@@ -6879,10 +6648,10 @@
* });
* // => { 'name': 'fred' }
*/
- function pick(object, predicate, thisArg) {
+ function pick(object, callback, thisArg) {
var result = {};
- if (typeof predicate != 'function') {
+ if (typeof callback != 'function') {
var index = -1,
props = baseFlatten(arguments, true, false, 1),
length = isObject(object) ? props.length : 0;
@@ -6894,9 +6663,9 @@
}
}
} else {
- predicate = lodash.createCallback(predicate, thisArg, 3);
+ callback = lodash.createCallback(callback, thisArg, 3);
baseForIn(object, function(value, key, object) {
- if (predicate(value, key, object)) {
+ if (callback(value, key, object)) {
result[key] = value;
}
});
@@ -6941,16 +6710,15 @@
if (isArr) {
accumulator = [];
} else {
- if (isObject(object)) {
- var ctor = object.constructor,
- proto = ctor && ctor.prototype;
- }
+ var ctor = object && object.constructor,
+ proto = ctor && ctor.prototype;
+
accumulator = baseCreate(proto);
}
}
if (callback) {
callback = lodash.createCallback(callback, thisArg, 4);
- (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
+ (isArr ? baseEach : baseForOwn)(object, function(value, index, object) {
return callback(accumulator, value, index, object);
});
}
@@ -6958,90 +6726,39 @@
}
/**
- * Creates an array of the own enumerable property values of `object`.
+ * Creates an array composed of the own enumerable property values of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
- * @returns {Array} Returns the array of property values.
+ * @returns {Array} Returns an 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] (property order is not guaranteed across environments)
+ * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
- return baseValues(object, keys);
- }
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = Array(length);
- /**
- * Creates an array of the own and inherited enumerable property values
- * of `object`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @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] (property order is not guaranteed across environments)
- */
- function valuesIn(object) {
- return baseValues(object, keysIn);
+ while (++index < length) {
+ result[index] = object[props[index]];
+ }
+ return result;
}
/*--------------------------------------------------------------------------*/
/**
- * Converts `string` to camel case.
- * See [Wikipedia](http://en.wikipedia.org/wiki/CamelCase) for more details.
+ * Converts the first character of `string` to upper case.
*
* @static
* @memberOf _
* @category Strings
- * @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) {
- if (!index && reAllCaps.test(word)) {
- return result + word.toLowerCase();
- }
- return result + (word.charAt(0)[index ? 'toUpperCase' : 'toLowerCase']() + word.slice(1));
- });
-
- /**
- * Capitalizes the first character of `string`.
- *
- * @static
- * @memberOf _
- * @category Strings
- * @param {string} [string=''] The string to capitalize.
+ * @param {string} string The string to capitalize.
* @returns {string} Returns the capitalized string.
* @example
*
@@ -7056,37 +6773,6 @@
return string.charAt(0).toUpperCase() + string.slice(1);
}
- /**
- * Checks if `string` ends with a given target string.
- *
- * @static
- * @memberOf _
- * @category Strings
- * @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.
@@ -7101,7 +6787,7 @@
* @static
* @memberOf _
* @category Strings
- * @param {string} [string=''] The string to escape.
+ * @param {string} string The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
@@ -7112,234 +6798,6 @@
return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
}
- /**
- * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*",
- * "+", "(", ")", "[", "]", "{" and "}" in `string`.
- *
- * @static
- * @memberOf _
- * @category Strings
- * @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) {
- return string == null ? '' : String(string).replace(reRegExpChars, '\\$&');
- }
-
- /**
- * 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 Strings
- * @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 Strings
- * @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 Strings
- * @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 createPad(string, length, chars) + 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 Strings
- * @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 + createPad(string, length, chars);
- }
-
- /**
- * Repeats the given string `n` times.
- *
- * @static
- * @memberOf _
- * @category Strings
- * @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);
- 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 Strings
- * @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 Strings
- * @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-escaped interpolated data properties in
@@ -7349,8 +6807,8 @@
* settings object is provided it will override `_.templateSettings` for the
* template.
*
- * Note: In the development build, `_.template` utilizes `sourceURL`s for easier debugging.
- * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+ * Note: In the development build, `_.template` utilizes sourceURLs for easier
+ * debugging. See [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
@@ -7362,17 +6820,17 @@
* @static
* @memberOf _
* @category Strings
- * @param {string} [string=''] The template string.
- * @param {Object} [data] The data object used to populate the template string.
+ * @param {string} text The template text.
+ * @param {Object} [data] The data object used to populate the text.
* @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 local variables.
* @param {RegExp} [options.interpolate] The "interpolate" delimiter.
- * @param {string} [options.sourceURL] The `sourceURL` of the template's compiled source.
+ * @param {string} [options.sourceURL] The sourceURL of the template's compiled source.
* @param {string} [options.variable] The data object variable name.
* @returns {Function|string} Returns the interpolated string if a data object
- * is provided, else the compiled template function.
+ * is provided, else it returns a template function.
* @example
*
* // using the "interpolate" delimiter to create a compiled template
@@ -7407,7 +6865,7 @@
* _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
* // => 'fredbarney'
*
- * // using the `sourceURL` option to specify a custom `sourceURL` for the template
+ * // using the `sourceURL` option to specify a custom sourceURL for the template
* var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
* compiled(data);
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
@@ -7429,18 +6887,20 @@
* };\
* ');
*/
- function template(string, data, options) {
+ function template(text, data, options) {
// based on John Resig's `tmpl` implementation
// http://ejohn.org/blog/javascript-micro-templating/
// and Laura Doktorova's doT.js
// https://github.com/olado/doT
var settings = lodash.templateSettings;
- options = defaults({}, options, settings);
- string = String(string == null ? '' : string);
+ text = String(text || '');
- var imports = defaults({}, options.imports, settings.imports),
- importsKeys = keys(imports),
- importsValues = values(imports);
+ // avoid missing dependencies when `iteratorTemplate` is not defined
+ options = iteratorTemplate ? defaults({}, options, settings) : settings;
+
+ var imports = iteratorTemplate && defaults({}, options.imports, settings.imports),
+ importsKeys = iteratorTemplate ? keys(imports) : ['_'],
+ importsValues = iteratorTemplate ? values(imports) : [lodash];
var isEscaping,
isEvaluating,
@@ -7456,11 +6916,11 @@
(options.evaluate || reNoMatch).source + '|$'
, 'g');
- string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue);
// escape characters that cannot be included in string literals
- source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+ source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
// replace delimiters with snippets
if (escapeValue) {
@@ -7513,7 +6973,7 @@
source +
'return __p\n}';
- // Use a `sourceURL` for easier debugging.
+ // Use a sourceURL for easier debugging.
// http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
@@ -7539,7 +6999,7 @@
* @static
* @memberOf _
* @category Strings
- * @param {string} [string=''] The string to trim.
+ * @param {string} string The string to trim.
* @param {string} [chars=whitespace] The characters to trim.
* @returns {string} Returns the trimmed string.
* @example
@@ -7550,17 +7010,12 @@
* _.trim('-_-fred-_-', '_-');
* // => 'fred'
*/
- function trim(string, chars) {
- string = string == null ? '' : String(string);
- if (!string) {
- return string;
+ var trim = !nativeTrim ? shimTrim : function(string, chars) {
+ if (string == null) {
+ return '';
}
- if (chars == null) {
- return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);
- }
- chars = String(chars);
- return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);
- }
+ return chars == null ? nativeTrim.call(string) : shimTrim(string, chars);
+ };
/**
* Removes leading whitespace or specified characters from `string`.
@@ -7568,7 +7023,7 @@
* @static
* @memberOf _
* @category Strings
- * @param {string} [string=''] The string to trim.
+ * @param {string} string The string to trim.
* @param {string} [chars=whitespace] The characters to trim.
* @returns {string} Returns the trimmed string.
* @example
@@ -7579,17 +7034,12 @@
* _.trimLeft('-_-fred-_-', '_-');
* // => 'fred-_-'
*/
- function trimLeft(string, chars) {
- string = string == null ? '' : String(string);
- if (!string) {
- return string;
+ var trimLeft = !nativeTrimLeft ? shimTrimLeft : function(string, chars) {
+ if (string == null) {
+ return '';
}
- if (chars == null) {
- return string.slice(trimmedLeftIndex(string))
- }
- chars = String(chars);
- return string.slice(charsLeftIndex(string, chars));
- }
+ return chars == null ? nativeTrimLeft.call(string) : shimTrimLeft(string, chars);
+ };
/**
* Removes trailing whitespace or specified characters from `string`.
@@ -7597,7 +7047,7 @@
* @static
* @memberOf _
* @category Strings
- * @param {string} [string=''] The string to trim.
+ * @param {string} string The string to trim.
* @param {string} [chars=whitespace] The characters to trim.
* @returns {string} Returns the trimmed string.
* @example
@@ -7608,96 +7058,12 @@
* _.trimRight('-_-fred-_-', '_-');
* // => '-_-fred'
*/
- function trimRight(string, chars) {
- string = string == null ? '' : String(string);
- if (!string) {
- return string;
+ var trimRight = !nativeTrimRight ? shimTrimRight : function(string, chars) {
+ if (string == null) {
+ return '';
}
- if (chars == null) {
- return string.slice(0, trimmedRightIndex(string) + 1)
- }
- chars = String(chars);
- return string.slice(0, charsRightIndex(string, chars) + 1);
- }
-
- /**
- * Truncates `string` if it is longer than the given maximum string length.
- * The last characters of the truncated string will be replaced with the
- * omission string which defaults to "...".
- *
- * @static
- * @memberOf _
- * @category Strings
- * @param {string} [string=''] The string to truncate.
- * @param {Object|number} [options] The options object or maximum string length.
- * @param {number} [options.length=30] The maximum string length.
- * @param {string} [options.omission='...'] The string used to indicate text is omitted.
- * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
- * @returns {string} Returns the truncated string.
- * @example
- *
- * _.truncate('hi-diddly-ho there, neighborino');
- * // => 'hi-diddly-ho there, neighbo...'
- *
- * _.truncate('hi-diddly-ho there, neighborino', 24);
- * // => 'hi-diddly-ho there, n...'
- *
- * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' });
- * // => 'hi-diddly-ho there,...'
- *
- * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ });
- * //=> 'hi-diddly-ho there...'
- *
- * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' });
- * // => 'hi-diddly-ho there, neig [...]'
- */
- function truncate(string, options) {
- var length = 30,
- omission = '...';
-
- if (options && isObject(options)) {
- var separator = 'separator' in options ? options.separator : separator;
- length = 'length' in options ? +options.length || 0 : length;
- omission = 'omission' in options ? String(options.omission) : omission;
- }
- else if (options != null) {
- length = +options || 0;
- }
- string = string == null ? '' : String(string);
- if (length >= string.length) {
- return string;
- }
- var end = length - omission.length;
- if (end < 1) {
- return omission;
- }
- var result = string.slice(0, end);
- if (separator == null) {
- return result + omission;
- }
- if (isRegExp(separator)) {
- if (string.slice(end).search(separator)) {
- var match,
- newEnd,
- substring = string.slice(0, end);
-
- if (!separator.global) {
- separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');
- }
- separator.lastIndex = 0;
- while ((match = separator.exec(substring))) {
- newEnd = match.index;
- }
- result = result.slice(0, newEnd == null ? end : newEnd);
- }
- } else if (string.indexOf(separator, end) != end) {
- var index = result.lastIndexOf(separator);
- if (index > -1) {
- result = result.slice(0, index);
- }
- }
- return result + omission;
- }
+ return chars == null ? nativeTrimRight.call(string) : shimTrimRight(string, chars);
+ };
/**
* The inverse of `_.escape`; this method converts the HTML entities
@@ -7710,7 +7076,7 @@
* @static
* @memberOf _
* @category Strings
- * @param {string} [string=''] The string to unescape.
+ * @param {string} string The string to unescape.
* @returns {string} Returns the unescaped string.
* @example
*
@@ -7749,7 +7115,7 @@
}
/**
- * Creates a function bound to an optional `thisArg`. If `func` is a property
+ * Produces a callback bound to an optional `thisArg`. If `func` is a property
* name the created callback will return the property value for a given element.
* If `func` is an object the created callback will return `true` for elements
* that contain the equivalent object properties, otherwise it will return `false`.
@@ -7761,7 +7127,7 @@
* @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.
+ * @returns {Function} Returns a callback function.
* @example
*
* var characters = [
@@ -7783,11 +7149,11 @@
function createCallback(func, thisArg, argCount) {
var type = typeof func;
if (type == 'function' || func == null) {
- return (typeof thisArg == 'undefined' || !(func && 'prototype' in func)) &&
+ return (typeof thisArg == 'undefined' || !('prototype' in func)) &&
func || baseCreateCallback(func, thisArg, argCount);
}
// handle "_.pluck" and "_.where" style callback shorthands
- return type == 'object' ? matches(func) : property(func);
+ return type != 'object' ? property(func) : matches(func);
}
/**
@@ -7809,9 +7175,9 @@
}
/**
- * Creates a "_.where" style predicate function which performs a deep comparison
- * between a given object and the `source` object, returning `true` if the given
- * object has equivalent property values, else `false`.
+ * Creates a "_.where" style function, which performs a deep comparison
+ * between a given object and the `source` object, returning `true` if the
+ * given object has equivalent property values, else `false`.
*
* @static
* @memberOf _
@@ -7834,33 +7200,32 @@
* // => { 'name': 'barney', 'age': 36 }
*/
function matches(source) {
+ source || (source = {});
+
var props = keys(source),
- propsLength = props.length,
key = props[0],
- value = propsLength && source[key];
+ a = source[key];
// fast path the common case of providing an object with a single
// property containing a primitive value
- if (propsLength == 1 && value === value && !isObject(value)) {
+ if (props.length == 1 && a === a && !isObject(a)) {
return function(object) {
- if (!(object && hasOwnProperty.call(object, key))) {
+ if (!hasOwnProperty.call(object, key)) {
return false;
}
// treat `-0` vs. `+0` as not equal
- var other = object[key];
- return value === other && (value !== 0 || (1 / value == 1 / other));
+ var b = object[key];
+ return a === b && (a !== 0 || (1 / a == 1 / b));
};
}
return function(object) {
- var length = propsLength;
- if (length && !object) {
- return false;
- }
- var result = true;
+ var length = props.length,
+ result = false;
+
while (length--) {
var key = props[length];
if (!(result = hasOwnProperty.call(object, key) &&
- baseIsEqual(object[key], source[key], null, true))) {
+ baseIsEqual(object[key], source[key], null, true))) {
break;
}
}
@@ -7875,12 +7240,10 @@
* @static
* @memberOf _
* @category Utilities
- * @param {Function|Object} [object=this] object The destination object.
+ * @param {Function|Object} [object=lodash] object The destination object.
* @param {Object} source The object of functions to add.
* @param {Object} [options] The options object.
- * @param {boolean} [options.chain=true] Specify whether the functions added
- * are chainable.
- * @returns {Function|Object} Returns `object`.
+ * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
* @example
*
* function vowels(string) {
@@ -7909,7 +7272,7 @@
options = source;
}
source = object;
- object = this;
+ object = lodash;
methodNames = functions(source);
}
if (options === false) {
@@ -7946,11 +7309,10 @@
}(func));
}
}
- return object;
}
/**
- * Reverts the `_` variable to its previous value and returns a reference to
+ * Reverts the '_' variable to its previous value and returns a reference to
* the `lodash` function.
*
* @static
@@ -8001,8 +7363,8 @@
/**
* Converts `value` to an integer of the specified radix. If `radix` is
- * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,
- * in which case a `radix` of `16` is used.
+ * `undefined` or `0` a `radix` of `10` is used unless the `value` is a
+ * hexadecimal, in which case a `radix` of `16` is used.
*
* Note: This method avoids differences in native ES3 and ES5 `parseInt`
* implementations. See the [ES5 spec](http://es5.github.io/#E)
@@ -8013,7 +7375,7 @@
* @category Utilities
* @param {string} value The value to parse.
* @param {number} [radix] The radix used to interpret the value to parse.
- * @returns {number} Returns the converted integer.
+ * @returns {number} Returns the new integer value.
* @example
*
* _.parseInt('08');
@@ -8028,7 +7390,7 @@
};
/**
- * Creates a "_.pluck" style function which returns the `key` value of a
+ * Creates a "_.pluck" style function, which returns the `key` value of a
* given object.
*
* @static
@@ -8053,14 +7415,14 @@
*/
function property(key) {
return function(object) {
- return object == null ? undefined : object[key];
+ return object[key];
};
}
/**
* Produces a random number between `min` and `max` (inclusive). If only one
* argument is provided a number between `0` and the given number will be
- * returned. If `floating` is truthy or either `min` or `max` are floats a
+ * returned. If `floating` is truey or either `min` or `max` are floats a
* floating-point number will be returned instead of an integer.
*
* @static
@@ -8069,7 +7431,7 @@
* @param {number} [min=0] The minimum possible value.
* @param {number} [max=1] The maximum possible value.
* @param {boolean} [floating=false] Specify returning a floating-point number.
- * @returns {number} Returns the random number.
+ * @returns {number} Returns a random number.
* @example
*
* _.random(0, 5);
@@ -8116,61 +7478,6 @@
return baseRandom(min, max);
}
- /**
- * Creates an array of numbers (positive and/or negative) progressing from
- * `start` up to but not including `end`. If `start` is less than `stop` a
- * zero-length range is created unless a negative `step` is specified.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {number} [start=0] The start of the range.
- * @param {number} end The end of the range.
- * @param {number} [step=1] The value to increment or decrement by.
- * @returns {Array} Returns the new array of numbers.
- * @example
- *
- * _.range(4);
- * // => [0, 1, 2, 3]
- *
- * _.range(1, 5);
- * // => [1, 2, 3, 4]
- *
- * _.range(0, 20, 5);
- * // => [0, 5, 10, 15]
- *
- * _.range(0, -4, -1);
- * // => [0, -1, -2, -3]
- *
- * _.range(1, 4, 0);
- * // => [1, 1, 1]
- *
- * _.range(0);
- * // => []
- */
- function range(start, end, step) {
- start = +start || 0;
- step = step == null ? 1 : (+step || 0);
-
- if (end == null) {
- end = start;
- start = 0;
- } else {
- end = +end || 0;
- }
- // use `Array(length)` so engines like Chakra and V8 avoid slower modes
- // http://youtu.be/XAqIpGU8ZZk#t=17m25s
- var index = -1,
- length = nativeMax(ceil((end - start) / (step || 1)), 0),
- result = Array(length);
-
- while (++index < length) {
- result[index] = start;
- start += step;
- }
- return result;
- }
-
/**
* Resolves the value of property `key` on `object`. If `key` is a function
* it will be invoked with the `this` binding of `object` and its result
@@ -8221,9 +7528,9 @@
* @memberOf _
* @category Utilities
* @param {number} n The number of times to execute the callback.
- * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Function} callback The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns the array of results.
+ * @returns {Array} Returns an array of the results of each `callback` execution.
* @example
*
* var diceRolls = _.times(3, _.partial(_.random, 1, 6));
@@ -8236,12 +7543,11 @@
* // => also calls `mage.castSpell(n)` three times
*/
function times(n, callback, thisArg) {
- n = n < 0 ? 0 : n >>> 0;
- callback = baseCreateCallback(callback, thisArg, 1);
-
+ n = (n = +n) > -1 ? n : 0;
var index = -1,
result = Array(n);
+ callback = baseCreateCallback(callback, thisArg, 1);
while (++index < n) {
result[index] = callback(index);
}
@@ -8291,10 +7597,6 @@
lodash.defer = defer;
lodash.delay = delay;
lodash.difference = difference;
- lodash.drop = drop;
- lodash.dropRight = dropRight;
- lodash.dropRightWhile = dropRightWhile;
- lodash.dropWhile = dropWhile;
lodash.filter = filter;
lodash.flatten = flatten;
lodash.forEach = forEach;
@@ -8311,7 +7613,6 @@
lodash.invert = invert;
lodash.invoke = invoke;
lodash.keys = keys;
- lodash.keysIn = keysIn;
lodash.map = map;
lodash.mapValues = mapValues;
lodash.matches = matches;
@@ -8319,8 +7620,6 @@
lodash.memoize = memoize;
lodash.merge = merge;
lodash.min = min;
- lodash.mixin = mixin;
- lodash.negate = negate;
lodash.omit = omit;
lodash.once = once;
lodash.pairs = pairs;
@@ -8334,6 +7633,7 @@
lodash.range = range;
lodash.reject = reject;
lodash.remove = remove;
+ lodash.removeAt = removeAt;
lodash.rest = rest;
lodash.shuffle = shuffle;
lodash.slice = slice;
@@ -8346,7 +7646,6 @@
lodash.union = union;
lodash.uniq = uniq;
lodash.values = values;
- lodash.valuesIn = valuesIn;
lodash.where = where;
lodash.without = without;
lodash.wrap = wrap;
@@ -8357,6 +7656,7 @@
// add aliases
lodash.callback = createCallback;
lodash.collect = map;
+ lodash.drop = rest;
lodash.each = forEach;
lodash.eachRight = forEachRight;
lodash.extend = assign;
@@ -8368,19 +7668,16 @@
lodash.unzip = zip;
// add functions to `lodash.prototype`
- mixin(lodash, assign({}, lodash));
+ mixin(assign({}, lodash));
/*--------------------------------------------------------------------------*/
// add functions that return unwrapped values when chaining
- lodash.camelCase = camelCase;
lodash.capitalize = capitalize;
lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash.contains = contains;
- lodash.endsWith = endsWith;
lodash.escape = escape;
- lodash.escapeRegExp = escapeRegExp;
lodash.every = every;
lodash.find = find;
lodash.findIndex = findIndex;
@@ -8388,7 +7685,6 @@
lodash.findLast = findLast;
lodash.findLastIndex = findLastIndex;
lodash.findLastKey = findLastKey;
- lodash.findWhere = findWhere;
lodash.has = has;
lodash.identity = identity;
lodash.indexOf = indexOf;
@@ -8399,7 +7695,6 @@
lodash.isElement = isElement;
lodash.isEmpty = isEmpty;
lodash.isEqual = isEqual;
- lodash.isError = isError;
lodash.isFinite = isFinite;
lodash.isFunction = isFunction;
lodash.isNaN = isNaN;
@@ -8410,31 +7705,24 @@
lodash.isRegExp = isRegExp;
lodash.isString = isString;
lodash.isUndefined = isUndefined;
- lodash.kebabCase = kebabCase;
lodash.lastIndexOf = lastIndexOf;
+ lodash.mixin = mixin;
lodash.noConflict = noConflict;
lodash.noop = noop;
lodash.now = now;
- lodash.pad = pad;
- lodash.padLeft = padLeft;
- lodash.padRight = padRight;
lodash.parseInt = parseInt;
lodash.random = random;
lodash.reduce = reduce;
lodash.reduceRight = reduceRight;
- lodash.repeat = repeat;
lodash.result = result;
lodash.runInContext = runInContext;
lodash.size = size;
lodash.some = some;
lodash.sortedIndex = sortedIndex;
- lodash.snakeCase = snakeCase;
- lodash.startsWith = startsWith;
lodash.template = template;
lodash.trim = trim;
lodash.trimLeft = trimLeft;
lodash.trimRight = trimRight;
- lodash.truncate = truncate;
lodash.unescape = unescape;
lodash.uniqueId = uniqueId;
@@ -8442,12 +7730,13 @@
lodash.all = every;
lodash.any = some;
lodash.detect = find;
+ lodash.findWhere = find;
lodash.foldl = reduce;
lodash.foldr = reduceRight;
lodash.include = contains;
lodash.inject = reduce;
- mixin(lodash, function() {
+ mixin(function() {
var source = {}
baseForOwn(lodash, function(func, methodName) {
if (!lodash.prototype[methodName]) {
@@ -8463,12 +7752,9 @@
lodash.first = first;
lodash.last = last;
lodash.sample = sample;
- lodash.take = take;
- lodash.takeRight = takeRight;
- lodash.takeRightWhile = takeRightWhile;
- lodash.takeWhile = takeWhile;
// add aliases
+ lodash.take = first;
lodash.head = first;
baseForOwn(lodash, function(func, methodName) {
@@ -8498,13 +7784,12 @@
// add "Chaining" functions to the wrapper
lodash.prototype.chain = wrapperChain;
- lodash.prototype.toJSON = wrapperValueOf;
lodash.prototype.toString = wrapperToString;
lodash.prototype.value = wrapperValueOf;
lodash.prototype.valueOf = wrapperValueOf;
// add `Array` functions that return unwrapped values
- arrayEach(['join', 'pop', 'shift'], function(methodName) {
+ baseEach(['join', 'pop', 'shift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
var chainAll = this.__chain__,
@@ -8517,7 +7802,7 @@
});
// add `Array` functions that return the existing wrapped value
- arrayEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+ baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
func.apply(this.__wrapped__, arguments);
@@ -8526,7 +7811,7 @@
});
// add `Array` functions that return new wrapped values
- arrayEach(['concat', 'splice'], function(methodName) {
+ baseEach(['concat', 'splice'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
@@ -8536,7 +7821,7 @@
// avoid array-like object bugs with `Array#shift` and `Array#splice`
// in IE < 9, Firefox < 10, Narwhal, and RingoJS
if (!support.spliceObjects) {
- arrayEach(['pop', 'shift', 'splice'], function(methodName) {
+ baseEach(['pop', 'shift', 'splice'], function(methodName) {
var func = arrayRef[methodName],
isSplice = methodName == 'splice';
@@ -8554,6 +7839,12 @@
};
});
}
+
+ // add pseudo private property to be used and removed during the build process
+ lodash._baseForIn = baseForIn;
+ lodash._iteratorTemplate = iteratorTemplate;
+ lodash._shimKeys = shimKeys;
+
return lodash;
}
diff --git a/test/test.js b/test/test.js
index 68b4f3a26..1212c6759 100644
--- a/test/test.js
+++ b/test/test.js
@@ -4,10 +4,7 @@
var undefined;
/** Used as the size to cover large array optimizations */
- var largeArraySize = 200;
-
- /** Used as the maximum length an array-like object */
- var maxSafeInteger = Math.pow(2, 53) - 1;
+ var LARGE_ARRAY_SIZE = 200;
/** Used as a reference to the global object */
var root = typeof global == 'object' && global || this;
@@ -28,9 +25,7 @@
push = Array.prototype.push,
slice = Array.prototype.slice,
system = root.system,
- toString = Object.prototype.toString;
-
- var JSON = root.JSON,
+ toString = Object.prototype.toString,
Worker = document && root.Worker;
/** The file path of the Lo-Dash file to test */
@@ -83,8 +78,8 @@
/** Detect if testing `npm` modules */
var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]);
- /** Detects if running in PhantomJS */
- var isPhantom = phantom || typeof callPhantom == 'function';
+ /** Detects if running in a PhantomJS web page */
+ var isPhantomPage = typeof callPhantom == 'function';
/** Detect if running in Rhino */
var isRhino = isJava && typeof global == 'function' && global().Array === root.Array;
@@ -185,7 +180,7 @@
return result;
}());
- /** Used to check problem JScript properties (a.k.a. the `[[DontEnum]]` bug) */
+ /** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */
var shadowedProps = [
'constructor',
'hasOwnProperty',
@@ -267,7 +262,6 @@
"'_array': [1, 2, 3],",
"'_boolean': new Boolean(false),",
"'_date': new Date,",
- "'_errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],",
"'_function': function() {},",
"'_nan': NaN,",
"'_null': null,",
@@ -275,7 +269,7 @@
"'_object': { 'a': 1, 'b': 2, 'c': 3 },",
"'_regexp': /x/,",
"'_string': new String('a'),",
- "'_undefined': undefined",
+ "'_undefined': undefined,",
'})'
].join('\n')));
}
@@ -294,12 +288,15 @@
}
// allow bypassing native checks
var _fnToString = Function.prototype.toString;
- setProperty(Function.prototype, 'toString', function wrapper() {
- setProperty(Function.prototype, 'toString', _fnToString);
- var result = this === Set ? this.toString() : _fnToString.call(this);
- setProperty(Function.prototype, 'toString', wrapper);
- return result;
- });
+ setProperty(Function.prototype, 'toString', (function() {
+ function fnToString() {
+ setProperty(Function.prototype, 'toString', _fnToString);
+ var result = this === Set ? this.toString() : _fnToString.call(this);
+ setProperty(Function.prototype, 'toString', fnToString);
+ return result;
+ }
+ return fnToString;
+ }()));
// fake DOM
setProperty(global, 'window', {});
@@ -321,7 +318,7 @@
var _now = Date.now;
setProperty(Date, 'now', function() {});
- var _create = create;
+ var _create = Object.create;
setProperty(Object, 'create', function() {});
var _defineProperty = Object.defineProperty;
@@ -333,17 +330,18 @@
var _keys = Object.keys;
setProperty(Object, 'keys', function() {});
- var _hasOwnProperty = Object.prototype.hasOwnProperty;
- setProperty(Object.prototype, 'hasOwnProperty', function(key) {
- if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0])) {
- throw new Error;
- }
- return _hasOwnProperty.call(this, key);
- });
-
var _contains = String.prototype.contains;
setProperty(String.prototype, 'contains', _contains ? function() {} : Boolean);
+ var _trim = String.prototype.trim;
+ setProperty(String.prototype, 'trim', _trim ? function() {} : String);
+
+ var _trimLeft = String.prototype.trimLeft;
+ setProperty(String.prototype, 'trimLeft', _trimLeft ? function() {} : String);
+
+ var _trimRight = String.prototype.trimRight;
+ setProperty(String.prototype, 'trimRight', _trimRight ? function() {} : String);
+
// clear cache so Lo-Dash can be reloaded
emptyObject(require.cache);
@@ -357,14 +355,22 @@
setProperty(Object, 'defineProperty', _defineProperty);
setProperty(Object, 'getPrototypeOf', _getPrototypeOf);
setProperty(Object, 'keys', _keys);
- setProperty(Object.prototype, 'hasOwnProperty', _hasOwnProperty);
setProperty(Function.prototype, 'toString', _fnToString);
- if (_contains) {
- setProperty(String.prototype, 'contains', _contains);
- } else {
- delete String.prototype.contains;
- }
+ _.forOwn({
+ 'contains': _contains,
+ 'trim': _trim,
+ 'trimLeft': _trimLeft,
+ 'trimRight': _trimRight
+ },
+ function(func, key) {
+ if (func) {
+ setProperty(String.prototype, key, func);
+ } else {
+ delete String.prototype[key];
+ }
+ });
+
delete global.window;
delete global.WinRTError;
delete Function.prototype._method;
@@ -387,7 +393,6 @@
'parent._._boolean = new Boolean(false);',
'parent._._date = new Date;',
"parent._._element = document.createElement('div');",
- 'parent._._errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError];',
'parent._._function = function() {};',
'parent._._nan = NaN;',
'parent._._null = null;',
@@ -423,7 +428,7 @@
(function() {
test('supports loading ' + basename + ' as the "lodash" module', 1, function() {
if (amd) {
- strictEqual((lodashModule || {}).moduleName, 'lodash');
+ equal((lodashModule || {}).moduleName, 'lodash');
}
else {
skipTest();
@@ -432,7 +437,7 @@
test('supports loading ' + basename + ' with the Require.js "shim" configuration option', 1, function() {
if (amd && /requirejs/.test(ui.loaderPath)) {
- strictEqual((shimmedModule || {}).moduleName, 'shimmed');
+ equal((shimmedModule || {}).moduleName, 'shimmed');
} else {
skipTest();
}
@@ -440,7 +445,7 @@
test('supports loading ' + basename + ' as the "underscore" module', 1, function() {
if (amd && !/dojo/.test(ui.loaderPath)) {
- strictEqual((underscoreModule || {}).moduleName, 'underscore');
+ equal((underscoreModule || {}).moduleName, 'underscore');
}
else {
skipTest();
@@ -458,7 +463,7 @@
setTimeout(attempt, 16);
return;
}
- strictEqual(actual, _.VERSION);
+ equal(actual, _.VERSION);
QUnit.start();
};
@@ -472,27 +477,28 @@
test('should not add `Function.prototype` extensions to lodash', 1, function() {
if (lodashBizarro) {
- ok(!('_method' in lodashBizarro));
+ equal('_method' in lodashBizarro, false);
}
else {
skipTest();
}
});
- test('should avoid overwritten native methods', 9, function() {
+ test('should avoid overwritten native methods', 12, function() {
function Foo() {}
function message(methodName) {
return '`_.' + methodName + '` should avoid overwritten native methods';
}
+ var object = { 'a': true };
- var object = { 'a': 1 },
- otherObject = { 'b': 2 },
- largeArray = _.times(largeArraySize, _.constant(object));
+ var largeArray = _.times(LARGE_ARRAY_SIZE, function() {
+ return object;
+ });
if (lodashBizarro) {
try {
- var actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'length': 0 })];
+ actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'length': 0 })];
} catch(e) {
actual = null;
}
@@ -514,11 +520,11 @@
deepEqual(actual[1], {}, message('Object.create'));
try {
- actual = lodashBizarro.bind(function() { return this.a; }, object);
+ var actual = lodashBizarro.bind(function() { return this.a; }, object);
} catch(e) {
actual = null;
}
- ok(!(expando in actual), message('Object.defineProperty'));
+ equal(expando in actual, false, message('Object.defineProperty'));
try {
actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])];
@@ -536,14 +542,14 @@
try {
actual = [
- lodashBizarro.difference([object, otherObject], largeArray),
+ lodashBizarro.difference([object], largeArray),
lodashBizarro.intersection(largeArray, [object]),
lodashBizarro.uniq(largeArray)
];
} catch(e) {
actual = null;
}
- deepEqual(actual, [[otherObject], [object], [object]], message('Set'));
+ deepEqual(actual, [[], [object], [object]], message('Set'));
try {
actual = lodashBizarro.contains('abc', 'c');
@@ -551,9 +557,23 @@
actual = null;
}
strictEqual(actual, true, message('String#contains'));
+
+ _.forEach(['trim', 'trimLeft', 'trimRight'], function(methodName) {
+ try {
+ var actual = [
+ lodashBizarro[methodName](whitespace + 'a b c' + whitespace),
+ lodashBizarro[methodName](''),
+ lodashBizarro[methodName]('-_-a-b-c-_-', '_-'),
+ lodashBizarro[methodName]('', '_-')
+ ];
+ } catch(e) {
+ actual = null;
+ }
+ ok(_.every(actual, _.isString), message('String#' + methodName));
+ });
}
else {
- skipTest(9);
+ skipTest(12);
}
});
}());
@@ -569,7 +589,7 @@
test('should return provided `lodash` instances', 1,function() {
var wrapped = _(false);
- strictEqual(_(wrapped), wrapped);
+ equal(_(wrapped), wrapped);
});
}());
@@ -578,23 +598,18 @@
QUnit.module('lodash.after');
(function() {
- function after(n, times) {
- var count = 0;
- _.times(times, _.after(n, function() { count++; }));
- return count;
- }
test('should create a function that executes `func` after `n` calls', 4, function() {
+ function after(n, times) {
+ var count = 0;
+ _.times(times, _.after(n, function() { count++; }));
+ return count;
+ }
+
strictEqual(after(5, 5), 1, 'after(n) should execute `func` after being called `n` times');
strictEqual(after(5, 4), 0, 'after(n) should not execute `func` unless called `n` times');
strictEqual(after(0, 0), 0, 'after(0) should not execute `func` immediately');
strictEqual(after(0, 1), 1, 'after(0) should execute `func` when called once');
});
-
- test('should coerce non-finite `n` values to `0`', 3, function() {
- _.each([-Infinity, NaN, Infinity], function(n) {
- strictEqual(after(n, 1), 1);
- });
- });
}());
/*--------------------------------------------------------------------------*/
@@ -611,6 +626,7 @@
this.a = 1;
this.c = 3;
}
+
Foo.prototype.b = 2;
deepEqual(_.assign({}, new Foo), { 'a': 1, 'c': 3 });
});
@@ -631,6 +647,14 @@
deepEqual(_.assign({ 'a': 1, 'b': 2 }, expected), expected);
});
+ test('should not error on `null` or `undefined` sources (test in IE < 9)', 1, function() {
+ try {
+ deepEqual(_.assign({}, null, undefined, { 'a': 1 }), { 'a': 1 });
+ } catch(e) {
+ ok(false);
+ }
+ });
+
test('should work with a callback', 1, function() {
var actual = _.assign({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) {
return typeof a == 'undefined' ? b : a;
@@ -693,7 +717,14 @@
deepEqual(actual, [1, 3]);
});
- _.each({
+ test('should work when used as a callback for `_.map`', 1, function() {
+ var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
+ actual = _.map(array, _.at);
+
+ deepEqual(actual, [[1], [5], [9]]);
+ });
+
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -726,7 +757,7 @@
var values = _.reject(falsey.slice(1), function(value) { return value == null; }),
expected = _.map(values, function(value) { return [value]; });
- var actual = _.map(values, function(value) {
+ var actual = _.map(values, function(value, index) {
try {
var bound = _.bind(fn, value);
return bound();
@@ -743,14 +774,14 @@
actual = bound('a');
ok(actual[0] === null || actual[0] && actual[0].Array);
- strictEqual(actual[1], 'a');
+ equal(actual[1], 'a');
_.times(2, function(index) {
bound = index ? _.bind(fn, undefined) : _.bind(fn);
actual = bound('b');
ok(actual[0] === undefined || actual[0] && actual[0].Array);
- strictEqual(actual[1], 'b');
+ equal(actual[1], 'b');
});
});
@@ -769,7 +800,7 @@
});
test('should support placeholders', 4, function() {
- if (!isModularize) {
+ if (_._iteratorTemplate) {
var object = {},
bound = _.bind(fn, object, _, 'b', _);
@@ -784,7 +815,7 @@
});
test('should create a function with a `length` of `0`', 2, function() {
- var fn = function(a, b, c) {},
+ var func = function(a, b, c) {},
bound = _.bind(fn, {});
strictEqual(bound.length, 0);
@@ -797,7 +828,6 @@
function Foo() {
return this;
}
-
var bound = _.bind(Foo, { 'a': 1 }),
newBound = new bound;
@@ -810,7 +840,6 @@
function Foo(value) {
return value && object;
}
-
var bound = _.bind(Foo),
object = {};
@@ -825,6 +854,10 @@
deepEqual(bound(['b'], 'c'), [object, 'a', ['b'], 'c']);
});
+ test('should throw a TypeError if `func` is not a function', 1, function() {
+ raises(function() { _.bind(); }, TypeError);
+ });
+
test('should return a wrapped value when chaining', 2, function() {
if (!isNpm) {
var object = {},
@@ -868,6 +901,7 @@
this._b = 2;
this.a = function() { return this._a; };
}
+
Foo.prototype.b = function() { return this._b; };
var object = new Foo;
@@ -951,122 +985,17 @@
var object = {
'name': 'fred',
'greet': function(greeting) {
- return this.name + ' says: ' + greeting;
+ return greeting + ' ' + this.name;
}
};
- var bound = _.bindKey(object, 'greet', 'hi');
- strictEqual(bound(), 'fred says: hi');
+ var func = _.bindKey(object, 'greet', 'hi');
+ equal(func(), 'hi fred');
object.greet = function(greeting) {
- return this.name + ' says: ' + greeting + '!';
+ return greeting + ' ' + this.name + '!';
};
- strictEqual(bound(), 'fred says: hi!');
- });
-
- test('should support placeholders', 4, function() {
- var object = {
- 'fn': function fn(a, b, c, d) {
- return slice.call(arguments);
- }
- };
-
- if (!isModularize) {
- var bound = _.bindKey(object, 'fn', _, 'b', _);
- deepEqual(bound('a', 'c'), ['a', 'b', 'c']);
- deepEqual(bound('a'), ['a', 'b', undefined]);
- deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']);
- deepEqual(bound(), [undefined, 'b', undefined]);
- }
- else {
- skipTest(4);
- }
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('case methods');
-
- _.each(['camel', 'kebab', 'snake'], function(caseName) {
- var methodName = caseName + 'Case',
- func = _[methodName];
-
- var expected = (function() {
- switch (caseName) {
- case 'camel': return 'helloWorld';
- case 'kebab': return 'hello-world';
- case 'snake': return 'hello_world';
- }
- }());
-
- var burredLetters = [
- '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF',
- '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF',
- '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF',
- '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF'
- ];
-
- var deburredLetters = [
- 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I',
- 'D', 'N', 'O', 'O', 'O', 'O', 'O', '', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th', 'ss',
- 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
- 'd', 'n', 'o', 'o', 'o', 'o', 'o', '', 'o', 'u', 'u', 'u', 'u', 'y', 'th', 'y'
- ];
-
- test('`_.' + methodName + '` should convert `string` to ' + caseName + ' case', 4, function() {
- _.each(['Hello world', 'helloWorld', '--hello-world', '__hello_world__'], function(string) {
- strictEqual(func(string), expected);
- });
- });
-
- test('`_.' + methodName + '` should handle double-converting strings', 4, function() {
- _.each(['Hello world', 'helloWorld', '--hello-world', '__hello_world__'], function(string) {
- strictEqual(func(func(string)), expected);
- });
- });
-
- test('`_.' + methodName + '` should deburr letters', 1, function() {
- var actual = _.map(burredLetters, function(burred, index) {
- var isCamel = caseName == 'camel',
- deburrLetter = deburredLetters[index];
-
- var string = isCamel
- ? func('z' + burred)
- : func(burred);
-
- var deburredString = isCamel
- ? 'z' + deburrLetter
- : deburrLetter.toLowerCase();
-
- return string == deburredString;
- });
-
- ok(_.every(actual, _.identity));
- });
-
- test('`_.' + methodName + '` should coerce `string` to a string', 2, function() {
- var string = 'Hello world';
- strictEqual(func(Object(string)), expected);
- strictEqual(func({ 'toString': _.constant(string) }), expected);
- });
- });
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.camelCase');
-
- (function() {
- test('should work with numbers', 3, function() {
- strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit');
- strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles');
- strictEqual(_.camelCase('xhr2 request'), 'xhr2Request');
- });
-
- test('should handle acronyms', 3, function() {
- strictEqual(_.camelCase('safe HTML'), 'safeHTML');
- strictEqual(_.camelCase('escape HTML entities'), 'escapeHTMLEntities');
- strictEqual(_.camelCase('XMLHttpRequest'), 'xmlHttpRequest');
+ equal(func(), 'hi fred!');
});
}());
@@ -1076,9 +1005,15 @@
(function() {
test('should capitalize the first character of a string', 3, function() {
- strictEqual(_.capitalize('fred'), 'Fred');
- strictEqual(_.capitalize('Fred'), 'Fred');
- strictEqual(_.capitalize(' fred'), ' fred');
+ equal(_.capitalize('fred'), 'Fred');
+ equal(_.capitalize('Fred'), 'Fred');
+ equal(_.capitalize(' fred'), ' fred');
+ });
+
+ test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() {
+ strictEqual(_.capitalize(null), '');
+ strictEqual(_.capitalize(undefined), '');
+ strictEqual(_.capitalize(''), '');
});
}());
@@ -1100,7 +1035,7 @@
test('should return the existing wrapper when chaining', 1, function() {
if (!isNpm) {
var wrapper = _({ 'a': 0 });
- strictEqual(wrapper.chain(), wrapper);
+ equal(wrapper.chain(), wrapper);
}
else {
skipTest();
@@ -1184,7 +1119,7 @@
Klass.prototype = { 'b': 1 };
var nonCloneable = {
- 'a DOM element': body,
+ 'an element': body,
'a function': Klass
};
@@ -1214,14 +1149,14 @@
actual = _.clone(expected);
deepEqual(actual, expected);
- ok(actual !== expected && actual[0] === expected[0]);
+ ok(actual != expected && actual[0] === expected[0]);
});
test('`_.clone` should perform a shallow clone when used as a callback for `_.map`', 1, function() {
var expected = [{ 'a': [0] }, { 'b': [1] }],
actual = _.map(expected, _.clone);
- ok(actual[0] !== expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b);
+ ok(actual[0] != expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b);
});
test('`_.cloneDeep` should deep clone objects with circular references', 1, function() {
@@ -1237,7 +1172,7 @@
ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object);
});
- _.each([
+ _.forEach([
'clone',
'cloneDeep'
],
@@ -1284,7 +1219,7 @@
return this[value];
}, { 'a': 'A' });
- strictEqual(actual, 'A');
+ equal(actual, 'A');
});
test('`_.' + methodName + '` should handle cloning if `callback` returns `undefined`', 1, function() {
@@ -1297,7 +1232,7 @@
actual = func(array);
strictEqual(actual.index, 2);
- strictEqual(actual.input, 'vwxyz');
+ equal(actual.input, 'vwxyz');
});
test('`_.' + methodName + '` should deep clone `lastIndex` regexp property', 1, function() {
@@ -1306,21 +1241,7 @@
regexp.exec('vwxyz');
var actual = func(regexp);
- strictEqual(actual.lastIndex, 3);
- });
-
- test('`_.' + methodName + '` should not error on DOM elements', 1, function() {
- if (document) {
- var element = document.createElement('div');
- try {
- strictEqual(func(element), element);
- } catch(e) {
- ok(false);
- }
- }
- else {
- skipTest();
- }
+ equal(actual.lastIndex, 3);
});
});
}(1, 2, 3));
@@ -1356,7 +1277,7 @@
};
var welcome = _.compose(greet, format);
- strictEqual(welcome('pebbles'), 'Hiya Penelope!');
+ equal(welcome('pebbles'), 'Hiya Penelope!');
});
test('should return a new function', 1, function() {
@@ -1406,59 +1327,40 @@
QUnit.module('lodash.contains');
(function() {
- _.each({
+ _.forEach({
'an `arguments` object': arguments,
- 'an array': [1, 2, 3, 4],
- 'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 4 },
- 'a string': '1234'
+ 'an array': [1, 2, 3, 1, 2, 3],
+ 'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3 },
+ 'a string': '123123'
},
function(collection, key) {
- var values = _.toArray(collection);
-
test('should work with ' + key + ' and return `true` for matched values', 1, function() {
strictEqual(_.contains(collection, 3), true);
});
test('should work with ' + key + ' and return `false` for unmatched values', 1, function() {
- strictEqual(_.contains(collection, 5), false);
+ strictEqual(_.contains(collection, 4), false);
});
- test('should work with ' + key + ' and a positive `fromIndex`', 2, function() {
- strictEqual(_.contains(collection, values[2], 2), true);
- strictEqual(_.contains(collection, values[1], 2), false);
+ test('should work with ' + key + ' and a positive `fromIndex`', 1, function() {
+ strictEqual(_.contains(collection, 1, 2), true);
});
- test('should work with ' + key + ' and a `fromIndex` >= `collection.length`', 12, function() {
- _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
+ test('should work with ' + key + ' and a `fromIndex` >= `collection.length`', 6, function() {
+ _.forEach([6, 8], function(fromIndex) {
strictEqual(_.contains(collection, 1, fromIndex), false);
strictEqual(_.contains(collection, undefined, fromIndex), false);
strictEqual(_.contains(collection, '', fromIndex), false);
});
});
- test('should work with ' + key + ' and treat falsey `fromIndex` values as `0`', 1, function() {
- var expected = _.map(falsey, _.constant(true));
-
- var actual = _.map(falsey, function(fromIndex) {
- return _.contains(collection, values[0], fromIndex);
- });
-
- deepEqual(actual, expected);
+ test('should work with ' + key + ' and a negative `fromIndex`', 1, function() {
+ strictEqual(_.contains(collection, 2, -3), true);
});
- test('should work with ' + key + ' and treat non-number `fromIndex` values as `0`', 1, function() {
- strictEqual(_.contains(collection, values[0], '1'), true);
- });
-
- test('should work with ' + key + ' and a negative `fromIndex`', 2, function() {
- strictEqual(_.contains(collection, values[2], -2), true);
- strictEqual(_.contains(collection, values[1], -2), false);
- });
-
- test('should work with ' + key + ' and a negative `fromIndex` <= negative `collection.length`', 3, function() {
- _.each([-4, -6, -Infinity], function(fromIndex) {
- strictEqual(_.contains(collection, values[0], fromIndex), true);
- });
+ test('should work with ' + key + ' and a negative `fromIndex` <= negative `collection.length`', 2, function() {
+ strictEqual(_.contains(collection, 1, -6), true);
+ strictEqual(_.contains(collection, 2, -8), true);
});
test('should work with ' + key + ' and return an unwrapped value when chaining', 1, function() {
@@ -1471,7 +1373,7 @@
});
});
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -1489,7 +1391,7 @@
test('should be aliased', 1, function() {
strictEqual(_.include, _.contains);
});
- }(1, 2, 3, 4));
+ }(1, 2, 3, 1, 2, 3));
/*--------------------------------------------------------------------------*/
@@ -1620,7 +1522,7 @@
test('should ignore primitive `prototype` arguments and use an empty object instead', 1, function() {
var primitives = [true, null, 1, 'a', undefined],
- expected = _.map(primitives, _.constant(true));
+ expected = _.map(primitives, function() { return true; });
var actual = _.map(primitives, function(value, index) {
return _.isPlainObject(index ? _.create(value) : _.create());
@@ -1635,60 +1537,28 @@
QUnit.module('lodash.callback');
(function() {
- test('should create a callback with a falsey `thisArg`', 1, function() {
- var values = _.map(falsey, function(value) {
- return Object(value == null ? root : value);
- });
+ test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() {
+ var fn = function() {
+ var result = [this.a];
+ push.apply(result, arguments);
+ return result;
+ };
- var actual = _.map(values, function(value) {
- var callback = _.callback(function() { return this; }, value);
- return callback();
- });
+ var expected = [1, 2, 3],
+ object = { 'a': 1 },
+ callback = _.createCallback(_.partial(fn, 2), object);
- deepEqual(actual, values);
- });
+ deepEqual(callback(3), expected);
- test('should return `_.identity` when `func` is nullish', 2, function() {
- var object = {};
- _.each([null, undefined], function(value) {
- var callback = _.callback(value);
- strictEqual(callback(object), object);
- });
- });
-
- test('should not error when `func` is nullish and a `thisArg` is provided', 2, function() {
- var object = {};
- _.each([null, undefined], function(value) {
- try {
- var callback = _.callback(value, {});
- strictEqual(callback(object), object);
- } catch(e) {
- ok(false);
- }
- });
- });
-
- test('should return a callback created by `_.matches` when `func` is an object', 2, function() {
- var callback = _.callback({ 'a': 1 });
- strictEqual(callback({ 'a': 1, 'b': 2 }), true);
- strictEqual(callback({}), false);
- });
-
- test('should return a callback created by `_.property` when `func` is a number or string', 2, function() {
- var array = ['a'],
- callback = _.callback(0);
-
- strictEqual(callback(array), 'a');
-
- callback = _.callback('0');
- strictEqual(callback(array), 'a');
+ callback = _.createCallback(_.partialRight(fn, 3), object);
+ deepEqual(callback(2), expected);
});
test('should work without an `argCount`', 1, function() {
var args,
expected = ['a', 'b', 'c', 'd', 'e'];
- var callback = _.callback(function() {
+ var callback = _.createCallback(function() {
args = slice.call(arguments);
});
@@ -1696,23 +1566,6 @@
deepEqual(args, expected);
});
- test('should work with functions created by `_.partial` and `_.partialRight`', 2, function() {
- function fn() {
- var result = [this.a];
- push.apply(result, arguments);
- return result;
- }
-
- var expected = [1, 2, 3],
- object = { 'a': 1 },
- callback = _.callback(_.partial(fn, 2), object);
-
- deepEqual(callback(3), expected);
-
- callback = _.callback(_.partialRight(fn, 3), object);
- deepEqual(callback(2), expected);
- });
-
test('should return the function provided if already bound with `Function#bind`', 1, function() {
function a() {}
@@ -1721,7 +1574,7 @@
if (bound && !('prototype' in bound)) {
var bound = a.bind(object);
- strictEqual(_.callback(bound, object), bound);
+ strictEqual(_.createCallback(bound, object), bound);
}
else {
skipTest();
@@ -1735,8 +1588,8 @@
var object = {};
if (_.support.funcDecomp) {
- strictEqual(_.callback(a, object), a);
- notStrictEqual(_.callback(b, object), b);
+ strictEqual(_.createCallback(a, object), a);
+ notStrictEqual(_.createCallback(b, object), b);
}
else {
skipTest(2);
@@ -1745,21 +1598,21 @@
test('should only write metadata to named functions', 3, function() {
function a() {};
- var b = function() {};
function c() {};
- var object = {};
+ var b = function() {},
+ object = {};
if (defineProperty && _.support.funcDecomp) {
- _.callback(a, object);
+ _.createCallback(a, object);
ok(expando in a);
- _.callback(b, object);
- ok(!(expando in b));
+ _.createCallback(b, object);
+ equal(expando in b, false);
if (_.support.funcNames) {
_.support.funcNames = false;
- _.callback(c, object);
+ _.createCallback(c, object);
ok(expando in c);
_.support.funcNames = true;
@@ -1777,8 +1630,8 @@
function a() {};
if (defineProperty && lodashBizarro) {
- lodashBizarro.callback(a, {});
- ok(!(expando in a));
+ lodashBizarro.createCallback(a, {});
+ equal(expando in a, false);
}
else {
skipTest();
@@ -1792,42 +1645,25 @@
(function() {
function fn(a, b, c, d) {
- return slice.call(arguments);
+ return a + b + c + d;
}
test('should curry based on the number of arguments provided', 3, function() {
- var curried = _.curry(fn),
- expected = [1, 2, 3, 4];
-
- deepEqual(curried(1)(2)(3)(4), expected);
- deepEqual(curried(1, 2)(3, 4), expected);
- deepEqual(curried(1, 2, 3, 4), expected);
+ var curried = _.curry(fn);
+ equal(curried(1)(2)(3)(4), 10);
+ equal(curried(1, 2)(3, 4), 10);
+ equal(curried(1, 2, 3, 4), 10);
});
test('should work with partialed methods', 2, function() {
var curried = _.curry(fn),
- expected = [1, 2, 3, 4];
-
- var a = _.partial(curried, 1),
+ a = _.partial(curried, 1),
b = _.bind(a, null, 2),
c = _.partialRight(b, 4),
d = _.partialRight(b(3), 4);
- deepEqual(c(3), expected);
- deepEqual(d(), expected);
- });
-
- test('should support placeholders', 4, function() {
- if (!isModularize) {
- var curried = _.curry(fn);
- deepEqual(curried(1)(_, 3)(_, 4)(2), [1, 2, 3, 4]);
- deepEqual(curried(_, 2)(1)(_, 4)(3), [1, 2, 3, 4]);
- deepEqual(curried(_, _, 3)(_, 2)(_, 4)(1), [1, 2, 3, 4]);
- deepEqual(curried(_, _, _, 4)(_, _, 3)(_, 2)(1), [1, 2, 3, 4]);
- }
- else {
- skipTest(4);
- }
+ equal(c(3), 10);
+ equal(d(), 10);
});
test('should return a function with a `length` of `0`', 6, function() {
@@ -1843,7 +1679,6 @@
function Foo(value) {
return value && object;
}
-
var curried = _.curry(Foo),
object = {};
@@ -1852,26 +1687,24 @@
});
test('should not alter the `this` binding', 9, function() {
- function fn(a, b, c) {
+ var fn = function(a, b, c) {
var value = this || {};
- return [value[a], value[b], value[c]];
- }
+ return value[a] + value[b] + value[c];
+ };
- var object = { 'a': 1, 'b': 2, 'c': 3 },
- expected = [1, 2, 3];
+ var object = { 'a': 1, 'b': 2, 'c': 3 };
+ equal(_.curry(_.bind(fn, object), 3)('a')('b')('c'), 6);
+ equal(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), 6);
+ equal(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), 6);
- deepEqual(_.curry(_.bind(fn, object), 3)('a')('b')('c'), expected);
- deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), expected);
- deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), expected);
-
- deepEqual(_.bind(_.curry(fn), object)('a')('b')('c'), Array(3));
- deepEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), Array(3));
- deepEqual(_.bind(_.curry(fn), object)('a', 'b', 'c'), expected);
+ ok(_.isEqual(_.bind(_.curry(fn), object)('a')('b')('c'), NaN));
+ ok(_.isEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), NaN));
+ equal(_.bind(_.curry(fn), object)('a', 'b', 'c'), 6);
object.curried = _.curry(fn);
- deepEqual(object.curried('a')('b')('c'), Array(3));
- deepEqual(object.curried('a', 'b')('c'), Array(3));
- deepEqual(object.curried('a', 'b', 'c'), expected);
+ ok(_.isEqual(object.curried('a')('b')('c'), NaN));
+ ok(_.isEqual(object.curried('a', 'b')('c'), NaN));
+ equal(object.curried('a', 'b', 'c'), 6);
});
}());
@@ -1889,10 +1722,10 @@
debounced();
debounced();
- strictEqual(count, 0);
+ equal(count, 0);
setTimeout(function() {
- strictEqual(count, 1);
+ equal(count, 1);
QUnit.start();
}, 96);
}
@@ -1963,12 +1796,12 @@
}
});
- asyncTest('should support a `leading` option', 7, function() {
+ asyncTest('should work with `leading` option', 7, function() {
if (!(isRhino && isModularize)) {
var withLeading,
counts = [0, 0, 0];
- _.each([true, { 'leading': true }], function(options, index) {
+ _.forEach([true, { 'leading': true }], function(options, index) {
var debounced = _.debounce(function(value) {
counts[index]++;
return value;
@@ -1977,10 +1810,10 @@
if (index == 1) {
withLeading = debounced;
}
- strictEqual(debounced('x'), 'x');
+ equal(debounced('x'), 'x');
});
- _.each([false, { 'leading': false }], function(options) {
+ _.forEach([false, { 'leading': false }], function(options) {
var withoutLeading = _.debounce(_.identity, 32, options);
strictEqual(withoutLeading('x'), undefined);
});
@@ -1998,7 +1831,7 @@
deepEqual(counts, [1, 1, 2]);
withLeading('x');
- strictEqual(counts[1], 2);
+ equal(counts[1], 2);
QUnit.start();
}, 64);
@@ -2009,7 +1842,7 @@
}
});
- asyncTest('should support a `trailing` option', 4, function() {
+ asyncTest('should work with `trailing` option', 4, function() {
if (!(isRhino && isModularize)) {
var withCount = 0,
withoutCount = 0;
@@ -2039,9 +1872,9 @@
}
});
- test('should support a `maxWait` option', 2, function() {
+ test('should work with `maxWait` option', 2, function() {
if (!(isRhino && isModularize)) {
- var limit = (argv || isPhantom) ? 1000 : 256,
+ var limit = (argv || isPhantomPage) ? 1000 : 256,
withCount = 0,
withoutCount = 0;
@@ -2105,7 +1938,7 @@
}
}
setTimeout(function() {
- strictEqual(count, 2);
+ equal(count, 2);
deepEqual(args, [object, 'a']);
QUnit.start();
}, 64);
@@ -2131,6 +1964,7 @@
this.a = 1;
this.c = 3;
}
+
Foo.prototype.b = 2;
deepEqual(_.defaults({ 'c': 2 }, new Foo), { 'a': 1, 'c': 2 });
});
@@ -2150,6 +1984,14 @@
var actual = _.defaults({ 'a': undefined }, { 'a': 1 });
strictEqual(actual.a, 1);
});
+
+ test('should not error on `null` or `undefined` sources (test in IE < 9)', 1, function() {
+ try {
+ deepEqual(_.defaults({ 'a': 1 }, null, undefined, { 'a': 2, 'b': 2 }), { 'a': 1, 'b': 2 });
+ } catch(e) {
+ ok(false);
+ }
+ });
}());
/*--------------------------------------------------------------------------*/
@@ -2285,8 +2127,6 @@
QUnit.module('lodash.difference');
(function() {
- var args = arguments;
-
test('should return the difference of the given arrays', 2, function() {
var actual = _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
deepEqual(actual, [1, 3, 4]);
@@ -2296,8 +2136,8 @@
});
test('should work with large arrays', 1, function() {
- var array1 = _.range(largeArraySize + 1),
- array2 = _.range(largeArraySize),
+ var array1 = _.range(LARGE_ARRAY_SIZE),
+ array2 = array1.slice(),
a = {},
b = {},
c = {};
@@ -2305,73 +2145,22 @@
array1.push(a, b, c);
array2.push(b, c, a);
- deepEqual(_.difference(array1, array2), [largeArraySize]);
+ deepEqual(_.difference(array1, array2), []);
});
test('should work with large arrays of objects', 1, function() {
- var object1 = {},
- object2 = {},
- largeArray = _.times(largeArraySize, _.constant(object1));
+ var object = {};
- deepEqual(_.difference([object1, object2], largeArray), [object2]);
- });
-
- test('should ignore values that are not arrays or `arguments` objects', 3, function() {
- var array = [0, 1, null, 3];
- deepEqual(_.difference(array, 3, null, { '0': 1 }), array);
- deepEqual(_.difference(null, array, null, [2, 1]), [0, null, 3]);
- deepEqual(_.difference(null, array, null, args), [0, null]);
- });
- }(1, 2, 3));
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.endsWith');
-
- (function() {
- var string = 'abc';
-
- test('should return `true` if a string ends with `target`', 1, function() {
- strictEqual(_.endsWith(string, 'c'), true);
- });
-
- test('should return `false` if a string does not end with `target`', 1, function() {
- strictEqual(_.endsWith(string, 'b'), false);
- });
-
- test('should work with a `position` argument', 1, function() {
- strictEqual(_.endsWith(string, 'b', 2), true);
- });
-
- test('should work with `position` >= `string.length`', 4, function() {
- _.each([3, 5, maxSafeInteger, Infinity], function(position) {
- strictEqual(_.endsWith(string, 'c', position), true);
- });
- });
-
- test('should treat falsey `position` values, except `undefined`, as `0`', 1, function() {
- var expected = _.map(falsey, _.constant(true));
-
- var actual = _.map(falsey, function(position) {
- return _.endsWith(string, position === undefined ? 'c' : '', position);
+ var largeArray = _.times(LARGE_ARRAY_SIZE, function() {
+ return object;
});
- deepEqual(actual, expected);
+ deepEqual(_.difference(largeArray, [object]), []);
});
- test('should treat a negative `position` as `0`', 6, function() {
- _.each([-1, -3, -Infinity], function(position) {
- ok(_.every(string, function(chr) {
- return _.endsWith(string, chr, position) === false;
- }));
- strictEqual(_.endsWith(string, '', position), true);
- });
- });
-
- test('should always return `true` when `target` is an empty string regardless of `position`', 1, function() {
- ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, maxSafeInteger, Infinity], function(position) {
- return _.endsWith(string, '', position, true);
- }));
+ test('should ignore individual secondary values', 1, function() {
+ var array = [1, null, 3];
+ deepEqual(_.difference(array, null, 3), array);
});
}());
@@ -2384,36 +2173,21 @@
unescaped = '&<>"\'\/';
test('should escape values', 1, function() {
- strictEqual(_.escape(unescaped), escaped);
+ equal(_.escape(unescaped), escaped);
});
test('should not escape the "/" character', 1, function() {
- strictEqual(_.escape('/'), '/');
+ equal(_.escape('/'), '/');
});
test('should handle strings with nothing to escape', 1, function() {
- strictEqual(_.escape('abc'), 'abc');
+ equal(_.escape('abc'), 'abc');
});
- test('should escape the same characters unescaped by `_.unescape`', 1, function() {
- strictEqual(_.escape(_.unescape(escaped)), escaped);
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.escapeRegExp');
-
- (function() {
- test('should escape values', 1, function() {
- var escaped = '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\/\\\\',
- unescaped = '.*+?^${}()|[\]\/\\';
-
- strictEqual(_.escapeRegExp(unescaped), escaped);
- });
-
- test('should handle strings with nothing to escape', 1, function() {
- strictEqual(_.escapeRegExp('abc'), 'abc');
+ test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() {
+ strictEqual(_.escape(null), '');
+ strictEqual(_.escape(undefined), '');
+ strictEqual(_.escape(''), '');
});
}());
@@ -2423,7 +2197,7 @@
(function() {
test('should return `true` for empty or falsey collections', 1, function() {
- var expected = _.map(empties, _.constant(true));
+ var expected = _.map(empties, function() { return true; });
var actual = _.map(empties, function(value) {
try {
@@ -2434,7 +2208,7 @@
deepEqual(actual, expected);
});
- test('should return `true` if the callback returns truthy for all elements in the collection', 1, function() {
+ test('should return `true` if the callback returns truey for all elements in the collection', 1, function() {
strictEqual(_.every([true, 1, 'x'], _.identity), true);
});
@@ -2460,13 +2234,12 @@
QUnit.module('source property checks');
- _.each(['assign', 'defaults', 'merge'], function(methodName) {
+ _.forEach(['assign', 'defaults', 'merge'], function(methodName) {
var func = _[methodName];
test('`_.' + methodName + '` should not assign inherited `source` properties', 1, function() {
function Foo() {}
Foo.prototype = { 'a': 1 };
-
deepEqual(func({}, new Foo), {});
});
@@ -2488,7 +2261,7 @@
expected[1] = undefined;
- ok('1' in actual);
+ ok(1 in actual);
deepEqual(actual, expected);
});
}
@@ -2498,7 +2271,7 @@
QUnit.module('strict mode checks');
- _.each(['assign', 'bindAll', 'defaults'], function(methodName) {
+ _.forEach(['assign', 'bindAll', 'defaults'], function(methodName) {
var func = _[methodName];
test('`_.' + methodName + '` should not throw strict mode errors', 1, function() {
@@ -2529,7 +2302,7 @@
QUnit.module('lodash.filter');
(function() {
- test('should return elements the `callback` returns truthy for', 1, function() {
+ test('should return elements the `callback` returns truey for', 1, function() {
var actual = _.filter([1, 2, 3], function(num) {
return num % 2;
});
@@ -2565,26 +2338,25 @@
/*--------------------------------------------------------------------------*/
- _.each(['find', 'findLast', 'findIndex', 'findLastIndex', 'findKey', 'findLastKey'], function(methodName) {
- QUnit.module('lodash.' + methodName);
+ (function() {
+ var objects = [
+ { 'a': 0, 'b': 0 },
+ { 'a': 1, 'b': 1 },
+ { 'a': 2, 'b': 2 }
+ ];
- var func = _[methodName];
+ _.forEach({
+ 'find': [objects[1], undefined, objects[2], objects[1]],
+ 'findLast': [objects[2], undefined, objects[2], objects[2]],
+ 'findIndex': [1, -1, 2, 1],
+ 'findLastIndex': [2, -1, 2, 2],
+ 'findKey': ['1', undefined, '2', '1'],
+ 'findLastKey': ['2', undefined, '2', '2']
+ },
+ function(expected, methodName) {
+ QUnit.module('lodash.' + methodName);
- (function() {
- var objects = [
- { 'a': 0, 'b': 0 },
- { 'a': 1, 'b': 1 },
- { 'a': 2, 'b': 2 }
- ];
-
- var expected = ({
- 'find': [objects[1], undefined, objects[2], objects[1]],
- 'findLast': [objects[2], undefined, objects[2], objects[2]],
- 'findIndex': [1, -1, 2, 1],
- 'findLastIndex': [2, -1, 2, 2],
- 'findKey': ['1', undefined, '2', '1'],
- 'findLastKey': ['2', undefined, '2', '2']
- })[methodName];
+ var func = _[methodName];
test('should return the correct value', 1, function() {
strictEqual(func(objects, function(object) { return object.a; }), expected[0]);
@@ -2595,7 +2367,15 @@
});
test('should return `' + expected[1] + '` if value is not found', 1, function() {
- strictEqual(func(objects, function(object) { return object.a === 3; }), expected[1]);
+ strictEqual(func(objects, function(object) { return object.a == 3; }), expected[1]);
+ });
+
+ test('should work with an object for `collection`', 1, function() {
+ var actual = _.find({ 'a': 1, 'b': 2, 'c': 3 }, function(num) {
+ return num > 2;
+ });
+
+ equal(actual, 3);
});
test('should work with an object for `callback`', 1, function() {
@@ -2611,7 +2391,7 @@
emptyValues = /Index/.test(methodName) ? _.reject(empties, _.isPlainObject) : empties,
expecting = _.map(emptyValues, function() { return expected[1]; });
- _.each(emptyValues, function(value) {
+ _.forEach(emptyValues, function(value) {
try {
actual.push(func(value, { 'a': 3 }));
} catch(e) { }
@@ -2619,89 +2399,13 @@
deepEqual(actual, expecting);
});
- }());
- (function() {
- var expected = ({
- 'find': 1,
- 'findLast': 2,
- 'findKey': 'a',
- 'findLastKey': 'b'
- })[methodName];
-
- if (expected != null) {
- test('should work with an object for `collection`', 1, function() {
- var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(num) {
- return num < 3;
- });
-
- strictEqual(actual, expected);
- });
- }
- }());
-
- (function() {
- var expected = ({
- 'find': 'a',
- 'findLast': 'b',
- 'findIndex': 0,
- 'findLastIndex': 1
- })[methodName];
-
- if (expected != null) {
- test('should work with a string for `collection`', 1, function() {
- var actual = func('abc', function(chr, index) {
- return index < 2;
- });
-
- strictEqual(actual, expected);
- });
- }
if (methodName == 'find') {
- test('should be aliased', 1, function() {
+ test('should be aliased', 2, function() {
strictEqual(_.detect, func);
+ strictEqual(_.findWhere, func);
});
}
- }());
- });
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.findWhere');
-
- (function() {
- var objects = [
- { 'a': 1 },
- { 'a': 1 },
- { 'a': 1, 'b': 2 },
- { 'a': 2, 'b': 2 },
- { 'a': 3 }
- ];
-
- test('should filter by `source` properties', 6, function() {
- strictEqual(_.findWhere(objects, { 'a': 1 }), objects[0]);
- strictEqual(_.findWhere(objects, { 'a': 2 }), objects[3]);
- strictEqual(_.findWhere(objects, { 'a': 3 }), objects[4]);
- strictEqual(_.findWhere(objects, { 'b': 1 }), undefined);
- strictEqual(_.findWhere(objects, { 'b': 2 }), objects[2]);
- strictEqual(_.findWhere(objects, { 'a': 1, 'b': 2 }), objects[2]);
- });
-
- test('should work with a function for `source`', 1, function() {
- function source() {}
- source.a = 2;
-
- strictEqual(_.findWhere(objects, source), objects[3]);
- });
-
- test('should match all elements when provided an empty `source`', 1, function() {
- var expected = _.map(empties, _.constant(true));
-
- var actual = _.map(empties, function(value) {
- return _.findWhere(objects, value) === objects[0];
- });
-
- deepEqual(actual, expected);
});
}());
@@ -2726,26 +2430,14 @@
deepEqual(_.first(array, 2), [1, 2]);
});
- test('should treat falsey `n` values, except nullish, as `0`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return value == null ? 1 : [];
- });
-
- var actual = _.map(falsey, function(n) {
- return _.first(array, n);
- });
-
- deepEqual(actual, expected);
- });
-
test('should return an empty array when `n` < `1`', 3, function() {
- _.each([0, -1, -Infinity], function(n) {
+ _.forEach([0, -1, -2], function(n) {
deepEqual(_.first(array, n), []);
});
});
- test('should return all elements when `n` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
+ test('should return all elements when `n` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(n) {
deepEqual(_.first(array, n), array);
});
});
@@ -2901,22 +2593,26 @@
expected.push(undefined, undefined, undefined);
deepEqual(actual1, expected);
- ok('4' in actual1);
+ ok(4 in actual1);
deepEqual(actual2, expected);
- ok('4' in actual2);
+ ok(4 in actual2);
});
test('should work with extremely large arrays', 1, function() {
- // test in modern browsers
+ var expected = Array(5e5),
+ pass = true;
+
if (freeze) {
try {
- var expected = Array(5e5),
- actual = _.flatten([expected]);
-
- deepEqual(actual, expected)
+ var actual = _.flatten([expected]);
} catch(e) {
- ok(false);
+ pass = false;
+ }
+ if (pass) {
+ deepEqual(actual, expected);
+ } else {
+ ok(pass);
}
} else {
skipTest();
@@ -2959,11 +2655,10 @@
QUnit.module('forEach methods');
- _.each(['forEach', 'forEachRight'], function(methodName) {
- var func = _[methodName],
- isForEach = methodName == 'forEach';
+ _.forEach(['forEach', 'forEachRight'], function(methodName) {
+ var func = _[methodName];
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -2977,7 +2672,7 @@
values.push(value);
});
- if (isForEach) {
+ if (methodName == 'forEach') {
deepEqual(args, ['a', 0, collection]);
deepEqual(values, ['a', 'b', 'c']);
} else {
@@ -2988,7 +2683,7 @@
});
test('`_.' + methodName + '` should be aliased', 1, function() {
- if (isForEach) {
+ if (methodName == 'forEach') {
strictEqual(_.each, _.forEach);
} else {
strictEqual(_.eachRight, _.forEachRight);
@@ -3000,7 +2695,7 @@
QUnit.module('forIn methods');
- _.each(['forIn', 'forInRight'], function(methodName) {
+ _.forEach(['forIn', 'forInRight'], function(methodName) {
var func = _[methodName];
test('`_.' + methodName + '` iterates over inherited properties', 1, function() {
@@ -3017,7 +2712,7 @@
QUnit.module('forOwn methods');
- _.each(['forOwn', 'forOwnRight'], function(methodName) {
+ _.forEach(['forOwn', 'forOwnRight'], function(methodName) {
var func = _[methodName];
test('iterates over the `length` property', 1, function() {
@@ -3035,20 +2730,15 @@
(function() {
var methods = [
- 'countBy',
'every',
'filter',
+ 'forEach',
'forEachRight',
'forIn',
'forInRight',
'forOwn',
'forOwnRight',
- 'groupBy',
- 'indexBy',
'map',
- 'max',
- 'min',
- 'partition',
'reject',
'some'
];
@@ -3058,26 +2748,6 @@
'some'
];
- var collectionMethods = [
- 'countBy',
- 'every',
- 'filter',
- 'find',
- 'findLast',
- 'forEach',
- 'forEachRight',
- 'groupBy',
- 'indexBy',
- 'map',
- 'max',
- 'min',
- 'partition',
- 'reduce',
- 'reduceRight',
- 'reject',
- 'some'
- ];
-
var forInMethods = [
'forIn',
'forInRight'
@@ -3105,7 +2775,7 @@
'forOwnRight'
];
- _.each(methods, function(methodName) {
+ _.forEach(methods, function(methodName) {
var array = [1, 2, 3],
func = _[methodName];
@@ -3133,21 +2803,22 @@
function callback(num, index) {
actual = this[index];
}
+
func([1], callback, [2]);
- strictEqual(actual, 2);
+ equal(actual, 2);
func({ 'a': 1 }, callback, { 'a': 2 });
- strictEqual(actual, 2);
+ equal(actual, 2);
});
});
- _.each(_.difference(methods, boolMethods), function(methodName) {
+ _.forEach(_.difference(methods, boolMethods), function(methodName) {
var array = [1, 2, 3],
func = _[methodName];
test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() {
if (!isNpm) {
- var actual = _(array)[methodName](_.noop);
+ var actual = _(array)[methodName](noop);
ok(actual instanceof _);
}
else {
@@ -3156,7 +2827,7 @@
});
});
- _.each(_.difference(methods, forInMethods), function(methodName) {
+ _.forEach(_.difference(methods, forInMethods), function(methodName) {
var array = [1, 2, 3],
func = _[methodName];
@@ -3170,56 +2841,34 @@
});
});
- _.each(iterationMethods, function(methodName) {
+ _.forEach(iterationMethods, function(methodName) {
var array = [1, 2, 3],
func = _[methodName];
test('`_.' + methodName + '` should return the collection', 1, function() {
- strictEqual(func(array, Boolean), array);
+ equal(func(array, Boolean), array);
});
test('`_.' + methodName + '` should return the existing wrapper when chaining', 1, function() {
if (!isNpm) {
var wrapper = _(array);
- strictEqual(wrapper[methodName](_.noop), wrapper);
+ equal(wrapper[methodName](noop), wrapper);
}
else {
skipTest();
}
});
});
-
- _.each(collectionMethods, function(methodName) {
- var func = _[methodName];
-
- test('`_.' + methodName + '` should treat objects with lengths of `0` as array-like', 1, function() {
- var pass = true;
- func({ 'length': 0 }, function() { pass = false; }, 0);
- ok(pass);
- });
-
- test('`_.' + methodName + '` should not treat objects with negative lengths as array-like', 1, function() {
- var pass = false;
- func({ 'length': -1 }, function() { pass = true; }, 0);
- ok(pass);
- });
-
- test('`_.' + methodName + '` should not treat objects with non-number lengths as array-like', 1, function() {
- var pass = false;
- func({ 'length': '0' }, function() { pass = true; }, 0);
- ok(pass);
- });
- });
}());
/*--------------------------------------------------------------------------*/
QUnit.module('collection iteration bugs');
- _.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) {
+ _.forEach(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) {
var func = _[methodName];
- test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() {
+ test('`_.' + methodName + '` fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() {
var props = [];
func(shadowedObject, function(value, prop) { props.push(prop); });
deepEqual(props.sort(), shadowedProps);
@@ -3276,17 +2925,13 @@
QUnit.module('object assignments');
- _.each(['assign', 'defaults', 'merge'], function(methodName) {
+ _.forEach(['assign', 'defaults', 'merge'], function(methodName) {
var func = _[methodName];
- test('`_.' + methodName + '` should return `undefined` when no destination object is provided', 1, function() {
- strictEqual(func(), undefined);
- });
-
test('`_.' + methodName + '` should return the existing wrapper when chaining', 1, function() {
if (!isNpm) {
var wrapper = _({ 'a': 1 });
- strictEqual(wrapper[methodName]({ 'b': 2 }), wrapper);
+ equal(wrapper[methodName]({ 'b': 2 }), wrapper);
}
else {
skipTest();
@@ -3316,9 +2961,10 @@
test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
function Foo() {}
+ Foo.prototype.c = 3;
+
Foo.a = 1;
Foo.b = 2;
- Foo.prototype.c = 3;
var expected = { 'a': 1, 'b': 2 };
deepEqual(func({}, Foo), expected);
@@ -3331,31 +2977,9 @@
var array = [{ 'b': 2 }, { 'c': 3 }];
deepEqual(_.reduce(array, func, { 'a': 1}), { 'a': 1, 'b': 2, 'c': 3 });
});
-
- test('`_.' + methodName + '` should not error on nullish sources (test in IE < 9)', 1, function() {
- try {
- deepEqual(func({ 'a': 1 }, undefined, { 'b': 2 }, null), { 'a': 1, 'b': 2 });
- } catch(e) {
- ok(false);
- }
- });
-
- test('`_.' + methodName + '` should not error when `object` is nullish and source objects are provided', 1, function() {
- var expected = _.times(2, _.constant(true));
-
- var actual = _.map([null, undefined], function(value) {
- try {
- return _.isEqual(func(value, { 'a': 1 }), value);
- } catch(e) {
- return false;
- }
- });
-
- deepEqual(actual, expected);
- });
});
- _.each(['assign', 'merge'], function(methodName) {
+ _.forEach(['assign', 'merge'], function(methodName) {
var func = _[methodName];
test('`_.' + methodName + '` should pass the correct `callback` arguments', 2, function() {
@@ -3402,7 +3026,7 @@
QUnit.module('exit early');
- _.each(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) {
+ _.forEach(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) {
var func = _[methodName];
if (!func) {
return;
@@ -3420,7 +3044,7 @@
values = [];
func(object, function(value) { values.push(value); return false; });
- strictEqual(values.length, 1);
+ equal(values.length, 1);
});
});
@@ -3434,7 +3058,7 @@
stringObject = Object(stringLiteral),
expected = [stringLiteral, stringObject];
- var largeArray = _.times(largeArraySize, function(count) {
+ var largeArray = _.times(LARGE_ARRAY_SIZE, function(count) {
return count % 2 ? stringObject : stringLiteral;
});
@@ -3444,7 +3068,7 @@
deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []);
});
- test('lodash.memoize should support values that resolve to the `__proto__` key', 1, function() {
+ test('lodash.memoize should memoize values resolved to the `__proto__` key', 1, function() {
var count = 0,
memoized = _.memoize(function() { return ++count; });
@@ -3460,7 +3084,7 @@
(function() {
test('should return the function names of an object', 1, function() {
- var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.each };
+ var object = { 'a': 'a', 'b': _.identity, 'c': /x/, 'd': _.forEach };
deepEqual(_.functions(object), ['b', 'd']);
});
@@ -3469,7 +3093,8 @@
this.a = _.identity;
this.b = 'b'
}
- Foo.prototype.c = _.noop;
+
+ Foo.prototype.c = noop;
deepEqual(_.functions(new Foo), ['a', 'c']);
});
@@ -3571,7 +3196,7 @@
test('should return `false` for primitives', 1, function() {
var values = falsey.concat(1, 'a'),
- expected = _.map(values, _.constant(false));
+ expected = _.map(values, function() { return false; });
var actual = _.map(values, function(value) {
return _.has(value, 'valueOf');
@@ -3647,52 +3272,41 @@
var array = [1, 2, 3, 1, 2, 3];
test('should return the index of the first matched value', 1, function() {
- strictEqual(_.indexOf(array, 3), 2);
+ equal(_.indexOf(array, 3), 2);
});
test('should return `-1` for an unmatched value', 4, function() {
- strictEqual(_.indexOf(array, 4), -1);
- strictEqual(_.indexOf(array, 4, true), -1);
+ equal(_.indexOf(array, 4), -1);
+ equal(_.indexOf(array, 4, true), -1);
var empty = [];
- strictEqual(_.indexOf(empty, undefined), -1);
- strictEqual(_.indexOf(empty, undefined, true), -1);
+ equal(_.indexOf(empty, undefined), -1);
+ equal(_.indexOf(empty, undefined, true), -1);
});
test('should work with a positive `fromIndex`', 1, function() {
- strictEqual(_.indexOf(array, 1, 2), 3);
+ equal(_.indexOf(array, 1, 2), 3);
});
- test('should work with `fromIndex` >= `array.length`', 12, function() {
- _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
- strictEqual(_.indexOf(array, 1, fromIndex), -1);
- strictEqual(_.indexOf(array, undefined, fromIndex), -1);
- strictEqual(_.indexOf(array, '', fromIndex), -1);
+ test('should work with `fromIndex` >= `array.length`', 6, function() {
+ _.forEach([6, 8], function(fromIndex) {
+ equal(_.indexOf(array, 1, fromIndex), -1);
+ equal(_.indexOf(array, undefined, fromIndex), -1);
+ equal(_.indexOf(array, '', fromIndex), -1);
});
});
- test('should treat falsey `fromIndex` values as `0`', 1, function() {
- var expected = _.map(falsey, _.constant(0));
-
- var actual = _.map(falsey, function(fromIndex) {
- return _.indexOf(array, 1, fromIndex);
- });
-
- deepEqual(actual, expected);
- });
-
- test('should treat non-number `fromIndex` values as `0`', 1, function() {
- strictEqual(_.indexOf([1, 2, 3], 1, '1'), 0);
- });
-
test('should work with a negative `fromIndex`', 1, function() {
- strictEqual(_.indexOf(array, 2, -3), 4);
+ equal(_.indexOf(array, 2, -3), 4);
});
- test('should work with a negative `fromIndex` <= `-array.length`', 3, function() {
- _.each([-6, -8, -Infinity], function(fromIndex) {
- strictEqual(_.indexOf(array, 1, fromIndex), 0);
- });
+ test('should work with a negative `fromIndex` <= `-array.length`', 2, function() {
+ strictEqual(_.indexOf(array, 1, -6), 0);
+ strictEqual(_.indexOf(array, 2, -8), 1);
+ });
+
+ test('should ignore non-number `fromIndex` values', 1, function() {
+ strictEqual(_.indexOf([1, 2, 3], 1, '1'), 0);
});
test('should work with `isSorted`', 1, function() {
@@ -3705,8 +3319,6 @@
QUnit.module('custom `_.indexOf` methods');
(function() {
- function Foo() {}
-
function custom(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array.length;
@@ -3720,22 +3332,23 @@
return -1;
}
+ function Foo() {}
+
var array = [1, new Foo, 3, new Foo],
indexOf = _.indexOf;
- var largeArray = _.times(largeArraySize, function() {
+ var largeArray = _.times(LARGE_ARRAY_SIZE, function() {
return new Foo;
});
- test('`_.contains` should work with a custom `_.indexOf` method', 2, function() {
+ test('`_.contains` should work with a custom `_.indexOf` method', 1, function() {
if (!isModularize) {
_.indexOf = custom;
ok(_.contains(array, new Foo));
- ok(_.contains({ 'a': 1, 'b': new Foo, 'c': 3 }, new Foo));
_.indexOf = indexOf;
}
else {
- skipTest(2);
+ skipTest();
}
});
@@ -3790,7 +3403,7 @@
];
test('should accept a falsey `array` argument', 1, function() {
- var expected = _.map(falsey, _.constant([]));
+ var expected = _.map(falsey, function() { return []; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -3813,26 +3426,14 @@
deepEqual(_.initial([]), []);
});
- test('should treat falsey `n` values, except nullish, as `0`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return value == null ? [1, 2] : array;
- });
-
- var actual = _.map(falsey, function(n) {
- return _.initial(array, n);
- });
-
- deepEqual(actual, expected);
- });
-
test('should return all elements when `n` < `1`', 3, function() {
- _.each([0, -1, -Infinity], function(n) {
+ _.forEach([0, -1, -2], function(n) {
deepEqual(_.initial(array, n), array);
});
});
- test('should return an empty array when `n` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
+ test('should return an empty array when `n` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(n) {
deepEqual(_.initial(array, n), []);
});
});
@@ -3884,32 +3485,25 @@
QUnit.module('lodash.intersection');
(function() {
- var args = arguments;
-
test('should return the intersection of the given arrays', 1, function() {
var actual = _.intersection([1, 3, 2], [5, 2, 1, 4], [2, 1]);
deepEqual(actual, [1, 2]);
});
- test('should return an array of unique values', 2, function() {
- var array = [1, 1, 3, 2, 2];
- deepEqual(_.intersection(array, [5, 2, 2, 1, 4], [2, 1, 1]), [1, 2]);
- deepEqual(_.intersection(array), [1, 3, 2]);
+ test('should return an array of unique values', 1, function() {
+ var actual = _.intersection([1, 1, 3, 2, 2], [5, 2, 2, 1, 4], [2, 1, 1]);
+ deepEqual(actual, [1, 2]);
});
test('should work with large arrays of objects', 1, function() {
var object = {},
- largeArray = _.times(largeArraySize, _.constant(object));
+ expected = [object];
- deepEqual(_.intersection([object], largeArray), [object]);
- });
+ var largeArray = _.times(LARGE_ARRAY_SIZE, function() {
+ return object;
+ });
- test('should work with large arrays of objects', 2, function() {
- var object = {},
- largeArray = _.times(largeArraySize, _.constant(object));
-
- deepEqual(_.intersection([object], largeArray), [object]);
- deepEqual(_.intersection(_.range(largeArraySize), null, [1]), [1]);
+ deepEqual(_.intersection(expected, largeArray), expected);
});
test('should return a wrapped value when chaining', 2, function() {
@@ -3923,13 +3517,10 @@
}
});
- test('should ignore values that are not arrays or `arguments` objects', 3, function() {
- var array = [0, 1, null, 3];
- deepEqual(_.intersection(array, 3, null, { '0': 1 }), array);
- deepEqual(_.intersection(null, array, null, [2, 1]), [1]);
- deepEqual(_.intersection(null, array, null, args), [1, 3]);
+ test('should ignore individual secondary values', 1, function() {
+ deepEqual(_.intersection([1, null, 3], 3, null), []);
});
- }(1, 2, 3));
+ }());
/*--------------------------------------------------------------------------*/
@@ -3967,8 +3558,8 @@
(function() {
test('should invoke a methods on each element of a collection', 1, function() {
- var array = ['a', 'b', 'c'];
- deepEqual( _.invoke(array, 'toUpperCase'), ['A', 'B', 'C']);
+ var actual = _.invoke(['a', 'b', 'c'], 'toUpperCase');
+ deepEqual(actual, ['A', 'B', 'C']);
});
test('should work with a function `methodName` argument', 1, function() {
@@ -3983,15 +3574,6 @@
var object = { 'a': 1, 'b': 2, 'c': 3 };
deepEqual(_.invoke(object, 'toFixed', 1), ['1.0', '2.0', '3.0']);
});
-
- test('should treat number values for `collection` as empty', 1, function() {
- deepEqual(_.invoke(1), []);
- });
-
- test('should work with nullish elements', 1, function() {
- var array = ['a', null, undefined, 'd'];
- deepEqual(_.invoke(array, 'toUpperCase'), ['A', undefined, undefined, 'D']);
- });
}());
/*--------------------------------------------------------------------------*/
@@ -4005,8 +3587,8 @@
strictEqual(_.isArguments(args), true);
});
- test('should return `false` for non `arguments` objects', 10, function() {
- var expected = _.map(falsey, _.constant(false));
+ test('should return `false` for non `arguments` objects', 9, function() {
+ var expected = _.map(falsey, function() { return false; });
var actual = _.map(falsey, function(value, index) {
return index ? _.isArguments(value) : _.isArguments();
@@ -4015,10 +3597,9 @@
strictEqual(_.isArguments([1, 2, 3]), false);
strictEqual(_.isArguments(true), false);
strictEqual(_.isArguments(new Date), false);
- strictEqual(_.isArguments(new Error), false);
strictEqual(_.isArguments(_), false);
- strictEqual(_.isArguments({ '0': 1, 'callee': _.noop, 'length': 1 }), false);
- strictEqual(_.isArguments(1), false);
+ strictEqual(_.isArguments({ '0': 1, 'callee': noop, 'length': 1 }), false);
+ strictEqual(_.isArguments(0), false);
strictEqual(_.isArguments(/x/), false);
strictEqual(_.isArguments('a'), false);
@@ -4046,8 +3627,8 @@
strictEqual(_.isArray([1, 2, 3]), true);
});
- test('should return `false` for non arrays', 10, function() {
- var expected = _.map(falsey, _.constant(false));
+ test('should return `false` for non arrays', 9, function() {
+ var expected = _.map(falsey, function() { return false; });
var actual = _.map(falsey, function(value, index) {
return index ? _.isArray(value) : _.isArray();
@@ -4056,10 +3637,9 @@
strictEqual(_.isArray(args), false);
strictEqual(_.isArray(true), false);
strictEqual(_.isArray(new Date), false);
- strictEqual(_.isArray(new Error), false);
strictEqual(_.isArray(_), false);
strictEqual(_.isArray({ '0': 1, 'length': 1 }), false);
- strictEqual(_.isArray(1), false);
+ strictEqual(_.isArray(0), false);
strictEqual(_.isArray(/x/), false);
strictEqual(_.isArray('a'), false);
@@ -4090,7 +3670,7 @@
strictEqual(_.isBoolean(new Boolean(false)), true);
});
- test('should return `false` for non booleans', 10, function() {
+ test('should return `false` for non booleans', 9, function() {
var expected = _.map(falsey, function(value) { return value === false; });
var actual = _.map(falsey, function(value, index) {
@@ -4100,10 +3680,9 @@
strictEqual(_.isBoolean(args), false);
strictEqual(_.isBoolean([1, 2, 3]), false);
strictEqual(_.isBoolean(new Date), false);
- strictEqual(_.isBoolean(new Error), false);
strictEqual(_.isBoolean(_), false);
strictEqual(_.isBoolean({ 'a': 1 }), false);
- strictEqual(_.isBoolean(1), false);
+ strictEqual(_.isBoolean(0), false);
strictEqual(_.isBoolean(/x/), false);
strictEqual(_.isBoolean('a'), false);
@@ -4131,8 +3710,8 @@
strictEqual(_.isDate(new Date), true);
});
- test('should return `false` for non dates', 10, function() {
- var expected = _.map(falsey, _.constant(false));
+ test('should return `false` for non dates', 9, function() {
+ var expected = _.map(falsey, function() { return false; });
var actual = _.map(falsey, function(value, index) {
return index ? _.isDate(value) : _.isDate();
@@ -4141,10 +3720,9 @@
strictEqual(_.isDate(args), false);
strictEqual(_.isDate([1, 2, 3]), false);
strictEqual(_.isDate(true), false);
- strictEqual(_.isDate(new Error), false);
strictEqual(_.isDate(_), false);
strictEqual(_.isDate({ 'a': 1 }), false);
- strictEqual(_.isDate(1), false);
+ strictEqual(_.isDate(0), false);
strictEqual(_.isDate(/x/), false);
strictEqual(_.isDate('a'), false);
@@ -4166,8 +3744,6 @@
QUnit.module('lodash.isElement');
(function() {
- var args = arguments;
-
function Element() {
this.nodeType = 1;
}
@@ -4196,28 +3772,7 @@
}
});
- test('should return `false` for non DOM elements', 11, function() {
- var expected = _.map(falsey, _.constant(false));
-
- var actual = _.map(falsey, function(value, index) {
- return index ? _.isElement(value) : _.isElement();
- });
-
- strictEqual(_.isElement(args), false);
- strictEqual(_.isElement([1, 2, 3]), false);
- strictEqual(_.isElement(true), false);
- strictEqual(_.isElement(new Date), false);
- strictEqual(_.isElement(new Error), false);
- strictEqual(_.isElement(_), false);
- strictEqual(_.isElement({ 'a': 1 }), false);
- strictEqual(_.isElement(1), false);
- strictEqual(_.isElement(/x/), false);
- strictEqual(_.isElement('a'), false);
-
- deepEqual(actual, expected);
- });
-
- test('should work with DOM elements from another realm', 1, function() {
+ test('should work with elements from another realm', 1, function() {
if (_._element) {
strictEqual(_.isElement(_._element), true);
}
@@ -4225,7 +3780,7 @@
skipTest();
}
});
- }(1, 2, 3));
+ }());
/*--------------------------------------------------------------------------*/
@@ -4235,7 +3790,7 @@
var args = arguments;
test('should return `true` for empty or falsey values', 3, function() {
- var expected = _.map(empties, _.constant(true));
+ var expected = _.map(empties, function() { return true; });
var actual = _.map(empties, function(value) {
return _.isEmpty(value);
@@ -4252,12 +3807,21 @@
strictEqual(_.isEmpty('a'), false);
});
- test('should work with an object that has a `length` property', 1, function() {
- strictEqual(_.isEmpty({ 'length': 0 }), false);
+ test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() {
+ equal(_.isEmpty(shadowedObject), false);
});
- test('should work with `arguments` objects (test in IE < 9)', 1, function() {
- strictEqual(_.isEmpty(args), false);
+ test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
+ function Foo() {}
+ Foo.prototype.a = 1;
+ strictEqual(_.isEmpty(Foo), true);
+
+ Foo.prototype = { 'a': 1 };
+ strictEqual(_.isEmpty(Foo), true);
+ });
+
+ test('should work with an object that has a `length` property', 1, function() {
+ strictEqual(_.isEmpty({ 'length': 0 }), false);
});
test('should work with jQuery/MooTools DOM query collections', 1, function() {
@@ -4267,36 +3831,12 @@
strictEqual(_.isEmpty(new Foo([])), true);
});
- test('should not treat objects with negative lengths as array-like', 1, function() {
- function Foo() {}
- Foo.prototype.length = -1;
-
- strictEqual(_.isEmpty(new Foo), true);
- });
-
- test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() {
- function Foo() {}
- Foo.prototype.length = maxSafeInteger + 1;
-
- strictEqual(_.isEmpty(new Foo), true);
- });
-
- test('should not treat objects with non-number lengths as array-like', 1, function() {
- strictEqual(_.isEmpty({ 'length': '0' }), false);
- });
-
- test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() {
- strictEqual(_.isEmpty(shadowedObject), false);
- });
-
- test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
- function Foo() {}
- Foo.prototype.a = 1;
-
- strictEqual(_.isEmpty(Foo), true);
-
- Foo.prototype = { 'a': 1 };
- strictEqual(_.isEmpty(Foo), true);
+ test('should work with `arguments` objects (test in IE < 9)', 1, function() {
+ if (!isPhantomPage) {
+ strictEqual(_.isEmpty(args), false);
+ } else {
+ skipTest();
+ }
});
test('should return an unwrapped value when intuitively chaining', 1, function() {
@@ -4350,14 +3890,14 @@
var primitive,
object = { 'toString': function() { return primitive; } },
values = [true, null, 1, 'a', undefined],
- expected = _.map(values, _.constant(false));
+ expected = _.map(values, function() { return false; });
var actual = _.map(values, function(value) {
primitive = value;
return _.isEqual(object, value);
});
- deepEqual(actual, expected);
+ ok(actual, expected);
});
test('should perform comparisons between arrays', 6, function() {
@@ -4471,7 +4011,7 @@
'f': ['a', new String('b'), 'c'],
'g': new Boolean(false),
'h': new Date(2012, 4, 23),
- 'i': _.noop,
+ 'i': noop,
'j': 'a'
}
};
@@ -4485,7 +4025,7 @@
'f': ['a', 'b', 'c'],
'g': false,
'h': new Date(2012, 4, 23),
- 'i': _.noop,
+ 'i': noop,
'j': 'a'
}
};
@@ -4494,7 +4034,9 @@
});
test('should perform comparisons between object instances', 4, function() {
- function Foo() { this.value = 1; }
+ function Foo() {
+ this.value = 1;
+ }
Foo.prototype.value = 1;
function Bar() {
@@ -4540,7 +4082,7 @@
strictEqual(_.isEqual(args1, args2), true);
- if (!isPhantom) {
+ if (!isPhantomPage) {
strictEqual(_.isEqual(args1, args3), false);
}
else {
@@ -4548,24 +4090,7 @@
}
});
- test('should treat `arguments` objects like `Object` objects', 2, function() {
- var args = (function() { return arguments; }(1, 2, 3)),
- object = { '0': 1, '1': 2, '2': 3, 'length': 3 };
-
- function Foo() {}
- Foo.prototype = object;
-
- strictEqual(_.isEqual(args, object), true);
-
- if (!isPhantom) {
- strictEqual(_.isEqual(args, new Foo), false);
- }
- else {
- skipTest();
- }
- });
-
- test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() {
+ test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() {
strictEqual(_.isEqual(shadowedObject, {}), false);
});
@@ -4711,11 +4236,11 @@
var actual = _.isEqual('a', 'a', function() { return 'a'; });
strictEqual(actual, true);
- var expected = _.map(falsey, _.constant(false));
+ var expected = _.map(falsey, function() { return false; });
actual = [];
- _.each(falsey, function(value) {
- actual.push(_.isEqual('a', 'b', _.constant(value)));
+ _.forEach(falsey, function(value) {
+ actual.push(_.isEqual('a', 'b', function() { return value; }));
});
deepEqual(actual, expected);
@@ -4738,13 +4263,13 @@
function Foo() { this.a = 1; }
Foo.prototype.constructor = null;
- var otherObject = { 'a': 1 };
- strictEqual(_.isEqual(new Foo, otherObject), false);
+ var other = { 'a': 1 };
+ strictEqual(_.isEqual(new Foo, other), false);
if (create) {
- var object = create(null);
+ var object = Object.create(null);
object.a = 1;
- strictEqual(_.isEqual(object, otherObject), true);
+ strictEqual(_.isEqual(object, other), true);
}
else {
skipTest();
@@ -4819,80 +4344,10 @@
skipTest();
}
});
-
- test('should not error on DOM elements', 1, function() {
- if (document) {
- var element1 = document.createElement('div'),
- element2 = element1.cloneNode(true);
-
- try {
- strictEqual(_.isEqual(element1, element2), false);
- } catch(e) {
- ok(false);
- }
- }
- else {
- skipTest();
- }
- });
}());
/*--------------------------------------------------------------------------*/
- QUnit.module('lodash.isError');
-
- (function() {
- var args = arguments;
-
- test('should return `true` for error objects', 1, function() {
- var errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],
- expected = _.map(errors, _.constant(true));
-
- var actual = _.map(errors, function(error) {
- return _.isError(error) === true;
- });
-
- deepEqual(actual, expected);
- });
-
- test('should return `false` for non-error objects', 10, function() {
- var expected = _.map(falsey, _.constant(false));
-
- var actual = _.map(falsey, function(value, index) {
- return index ? _.isError(value) : _.isError();
- });
-
- strictEqual(_.isError(args), false);
- strictEqual(_.isError([1, 2, 3]), false);
- strictEqual(_.isError(true), false);
- strictEqual(_.isError(new Date), false);
- strictEqual(_.isError(_), false);
- strictEqual(_.isError({ 'a': 1 }), false);
- strictEqual(_.isError(1), false);
- strictEqual(_.isError(/x/), false);
- strictEqual(_.isError('a'), false);
-
- deepEqual(actual, expected);
- });
-
- test('should work with an error object from another realm', 1, function() {
- if (_._object) {
- var expected = _.map(_._errors, _.constant(true));
-
- var actual = _.map(_._errors, function(error) {
- return _.isError(error) === true;
- });
-
- deepEqual(actual, expected);
- }
- else {
- skipTest();
- }
- });
- }(1, 2, 3));
-
- /*--------------------------------------------------------------------------*/
-
QUnit.module('lodash.isFinite');
(function() {
@@ -4910,13 +4365,12 @@
strictEqual(_.isFinite(-Infinity), false);
});
- test('should return `false` for non-numeric values', 9, function() {
+ test('should return `false` for non-numeric values', 8, function() {
strictEqual(_.isFinite(null), false);
strictEqual(_.isFinite(undefined), false);
strictEqual(_.isFinite([]), false);
strictEqual(_.isFinite(true), false);
strictEqual(_.isFinite(new Date), false);
- strictEqual(_.isFinite(new Error), false);
strictEqual(_.isFinite(''), false);
strictEqual(_.isFinite(' '), false);
strictEqual(_.isFinite('2px'), false);
@@ -4949,8 +4403,8 @@
strictEqual(_.isFunction(_), true);
});
- test('should return `false` for non functions', 10, function() {
- var expected = _.map(falsey, _.constant(false));
+ test('should return `false` for non functions', 9, function() {
+ var expected = _.map(falsey, function() { return false; });
var actual = _.map(falsey, function(value, index) {
return index ? _.isFunction(value) : _.isFunction();
@@ -4960,9 +4414,8 @@
strictEqual(_.isFunction([1, 2, 3]), false);
strictEqual(_.isFunction(true), false);
strictEqual(_.isFunction(new Date), false);
- strictEqual(_.isFunction(new Error), false);
strictEqual(_.isFunction({ 'a': 1 }), false);
- strictEqual(_.isFunction(1), false);
+ strictEqual(_.isFunction(0), false);
strictEqual(_.isFunction(/x/), false);
strictEqual(_.isFunction('a'), false);
@@ -4991,7 +4444,7 @@
strictEqual(_.isNaN(new Number(NaN)), true);
});
- test('should return `false` for non NaNs', 11, function() {
+ test('should return `false` for non NaNs', 10, function() {
var expected = _.map(falsey, function(value) { return value !== value; });
var actual = _.map(falsey, function(value, index) {
@@ -5002,10 +4455,9 @@
strictEqual(_.isNaN([1, 2, 3]), false);
strictEqual(_.isNaN(true), false);
strictEqual(_.isNaN(new Date), false);
- strictEqual(_.isNaN(new Error), false);
strictEqual(_.isNaN(_), false);
strictEqual(_.isNaN({ 'a': 1 }), false);
- strictEqual(_.isNaN(1), false);
+ strictEqual(_.isNaN(0), false);
strictEqual(_.isNaN(/x/), false);
strictEqual(_.isNaN('a'), false);
@@ -5033,7 +4485,7 @@
strictEqual(_.isNull(null), true);
});
- test('should return `false` for non nulls', 11, function() {
+ test('should return `false` for non nulls', 10, function() {
var expected = _.map(falsey, function(value) { return value === null; });
var actual = _.map(falsey, function(value, index) {
@@ -5044,10 +4496,9 @@
strictEqual(_.isNull([1, 2, 3]), false);
strictEqual(_.isNull(true), false);
strictEqual(_.isNull(new Date), false);
- strictEqual(_.isNull(new Error), false);
strictEqual(_.isNull(_), false);
strictEqual(_.isNull({ 'a': 1 }), false);
- strictEqual(_.isNull(1), false);
+ strictEqual(_.isNull(0), false);
strictEqual(_.isNull(/x/), false);
strictEqual(_.isNull('a'), false);
@@ -5076,7 +4527,7 @@
strictEqual(_.isNumber(new Number(0)), true);
});
- test('should return `false` for non numbers', 10, function() {
+ test('should return `false` for non numbers', 9, function() {
var expected = _.map(falsey, function(value) { return typeof value == 'number'; });
var actual = _.map(falsey, function(value, index) {
@@ -5087,7 +4538,6 @@
strictEqual(_.isNumber([1, 2, 3]), false);
strictEqual(_.isNumber(true), false);
strictEqual(_.isNumber(new Date), false);
- strictEqual(_.isNumber(new Error), false);
strictEqual(_.isNumber(_), false);
strictEqual(_.isNumber({ 'a': 1 }), false);
strictEqual(_.isNumber(/x/), false);
@@ -5117,12 +4567,11 @@
(function() {
var args = arguments;
- test('should return `true` for objects', 11, function() {
+ test('should return `true` for objects', 10, function() {
strictEqual(_.isObject(args), true);
strictEqual(_.isObject([1, 2, 3]), true);
strictEqual(_.isObject(new Boolean(false)), true);
strictEqual(_.isObject(new Date), true);
- strictEqual(_.isObject(new Error), true);
strictEqual(_.isObject(_), true);
strictEqual(_.isObject({ 'a': 1 }), true);
strictEqual(_.isObject(new Number(0)), true);
@@ -5138,7 +4587,7 @@
test('should return `false` for non objects', 1, function() {
var values = falsey.concat('a', true),
- expected = _.map(values, _.constant(false));
+ expected = _.map(values, function() { return false; });
var actual = _.map(values, function(value, index) {
return index ? _.isObject(value) : _.isObject();
@@ -5179,7 +4628,7 @@
// 2: Initial check with object, this is the other half of the trigger
_.isObject(obj);
- strictEqual(_.isObject(str), false);
+ equal(_.isObject(str), false);
});
}(1, 2, 3));
@@ -5202,7 +4651,7 @@
strictEqual(_.isPlainObject(new Foo(1)), false);
});
- test('should return `true` for objects with a `[[Prototype]]` of `null`', 1, function() {
+ test('should return `true` for objects a [[Prototype]] of `null`', 1, function() {
if (create) {
strictEqual(_.isPlainObject(create(null)), true);
} else {
@@ -5232,14 +4681,14 @@
}
});
- test('should return `false` for Object objects without a `[[Class]]` of "Object"', 3, function() {
+ test('should return `false` for Object objects without a [[Class]] of "Object"', 3, function() {
strictEqual(_.isPlainObject(arguments), false);
strictEqual(_.isPlainObject(Error), false);
strictEqual(_.isPlainObject(Math), false);
});
test('should return `false` for non objects', 3, function() {
- var expected = _.map(falsey, _.constant(false));
+ var expected = _.map(falsey, function() { return false; });
var actual = _.map(falsey, function(value, index) {
return index ? _.isPlainObject(value) : _.isPlainObject();
@@ -5272,8 +4721,8 @@
strictEqual(_.isRegExp(RegExp('x')), true);
});
- test('should return `false` for non regexes', 10, function() {
- var expected = _.map(falsey, _.constant(false));
+ test('should return `false` for non regexes', 9, function() {
+ var expected = _.map(falsey, function(value) { return false; });
var actual = _.map(falsey, function(value, index) {
return index ? _.isRegExp(value) : _.isRegExp();
@@ -5283,10 +4732,9 @@
strictEqual(_.isRegExp([1, 2, 3]), false);
strictEqual(_.isRegExp(true), false);
strictEqual(_.isRegExp(new Date), false);
- strictEqual(_.isRegExp(new Error), false);
strictEqual(_.isRegExp(_), false);
strictEqual(_.isRegExp({ 'a': 1 }), false);
- strictEqual(_.isRegExp(1), false);
+ strictEqual(_.isRegExp(0), false);
strictEqual(_.isRegExp('a'), false);
deepEqual(actual, expected);
@@ -5314,7 +4762,7 @@
strictEqual(_.isString(new String('a')), true);
});
- test('should return `false` for non strings', 10, function() {
+ test('should return `false` for non strings', 9, function() {
var expected = _.map(falsey, function(value) { return value === ''; });
var actual = _.map(falsey, function(value, index) {
@@ -5325,10 +4773,9 @@
strictEqual(_.isString([1, 2, 3]), false);
strictEqual(_.isString(true), false);
strictEqual(_.isString(new Date), false);
- strictEqual(_.isString(new Error), false);
strictEqual(_.isString(_), false);
strictEqual(_.isString({ '0': 1, 'length': 1 }), false);
- strictEqual(_.isString(1), false);
+ strictEqual(_.isString(0), false);
strictEqual(_.isString(/x/), false);
deepEqual(actual, expected);
@@ -5356,21 +4803,20 @@
strictEqual(_.isUndefined(undefined), true);
});
- test('should return `false` for non `undefined` values', 11, function() {
+ test('should return `false` for non `undefined` values', 10, function() {
var expected = _.map(falsey, function(value) { return value === undefined; });
var actual = _.map(falsey, function(value, index) {
- return index ? _.isUndefined(value) : _.isUndefined();
+ return _.isUndefined(value);
});
strictEqual(_.isUndefined(args), false);
strictEqual(_.isUndefined([1, 2, 3]), false);
strictEqual(_.isUndefined(true), false);
strictEqual(_.isUndefined(new Date), false);
- strictEqual(_.isUndefined(new Error), false);
strictEqual(_.isUndefined(_), false);
strictEqual(_.isUndefined({ 'a': 1 }), false);
- strictEqual(_.isUndefined(1), false);
+ strictEqual(_.isUndefined(0), false);
strictEqual(_.isUndefined(/x/), false);
strictEqual(_.isUndefined('a'), false);
@@ -5392,13 +4838,13 @@
QUnit.module('isType checks');
(function() {
- test('should return `false` for subclassed values', 8, function() {
+ test('should return `false` for subclassed values', 7, function() {
var funcs = [
- 'isArray', 'isBoolean', 'isDate', 'isError',
- 'isFunction', 'isNumber', 'isRegExp', 'isString'
+ 'isArray', 'isBoolean', 'isDate', 'isFunction',
+ 'isNumber', 'isRegExp', 'isString'
];
- _.each(funcs, function(methodName) {
+ _.forEach(funcs, function(methodName) {
function Foo() {}
Foo.prototype = root[methodName.slice(2)].prototype;
@@ -5422,7 +4868,7 @@
'isObject', 'isNull', 'isNumber', 'isRegExp', 'isString', 'isUndefined'
];
- _.each(funcs, function(methodName) {
+ _.forEach(funcs, function(methodName) {
var pass = true;
try {
_[methodName](xml);
@@ -5440,146 +4886,52 @@
/*--------------------------------------------------------------------------*/
- QUnit.module('keys methods');
+ QUnit.module('lodash.keys');
- _.each(['keys', 'keysIn'], function(methodName) {
- var args = arguments,
- func = _[methodName],
- isKeys = methodName == 'keys';
+ (function() {
+ var args = arguments;
- test('`_.' + methodName + '` should return the keys of an object', 1, function() {
- var object = { 'a': 1, 'b': 1 },
- actual = func(object);
-
- deepEqual(actual.sort(), ['a', 'b']);
+ test('should return the keys of an object', 1, function() {
+ var object = { 'a': 1, 'b': 1 };
+ deepEqual(_.keys(object), ['a', 'b']);
});
- test('`_.' + methodName + '` should treat sparse arrays as dense', 1, function() {
+ test('should work with sparse arrays', 1, function() {
var array = [1];
array[2] = 3;
-
- var actual = func(array);
- deepEqual(actual.sort(), ['0', '1', '2']);
+ deepEqual(_.keys(array), ['0', '2']);
});
- test('`_.' + methodName + '` should custom properties on arrays', 1, function() {
- var array = [1];
- array.a = 1;
-
- var actual = func(array);
- deepEqual(actual.sort(), ['0', 'a']);
- });
-
- test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of arrays', 1, function() {
- Array.prototype.a = 1;
- var expected = isKeys ? ['0'] : ['0', 'a'],
- actual = func([1]);
-
- deepEqual(actual.sort(), expected);
- delete Array.prototype.a;
- });
-
- test('`_.' + methodName + '` should work with `arguments` objects (test in IE < 9)', 1, function() {
- if (!isPhantom) {
- var actual = func(args);
- deepEqual(actual.sort(), ['0', '1', '2']);
+ test('should work with `arguments` objects (test in IE < 9)', 1, function() {
+ if (!isPhantomPage) {
+ deepEqual(_.keys(args), ['0', '1', '2']);
} else {
skipTest();
}
});
- test('`_.' + methodName + '` should custom properties on `arguments` objects', 1, function() {
- if (!isPhantom) {
- args.a = 1;
- var actual = func(args);
-
- deepEqual(actual.sort(), ['0', '1', '2', 'a']);
- delete args.a;
- } else {
- skipTest();
- }
- });
-
- test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of `arguments` objects', 1, function() {
- if (!isPhantom) {
- Object.prototype.a = 1;
- var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a'],
- actual = func(args);
-
- deepEqual(actual.sort(), expected);
- delete Object.prototype.a;
- } else {
- skipTest();
- }
- });
-
- test('`_.' + methodName + '` should work with string objects (test in IE < 9)', 1, function() {
- var actual = func(Object('abc'));
- deepEqual(actual.sort(), ['0', '1', '2']);
- });
-
- test('`_.' + methodName + '` should custom properties on string objects', 1, function() {
- var object = Object('a');
- object.a = 1;
-
- var actual = func(object);
- deepEqual(actual.sort(), ['0', 'a']);
- });
-
- test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of string objects', 1, function() {
- String.prototype.a = 1;
- var expected = isKeys ? ['0'] : ['0', 'a'],
- actual = func(Object('a'));
-
- deepEqual(actual.sort(), expected);
- delete String.prototype.a;
- });
-
- test('`_.' + methodName + '` fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() {
- var actual = func(shadowedObject);
- deepEqual(actual.sort(), shadowedProps);
- });
-
- test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
- function Foo() {}
- Foo.a = 1;
- Foo.b = 2;
- Foo.prototype.c = 3;
-
- var expected = ['a', 'b'],
- actual = func(Foo);
-
- deepEqual(actual.sort(), expected);
-
- Foo.prototype = { 'c': 3 };
- actual = func(Foo);
- deepEqual(actual.sort(), expected);
- });
-
- test('`_.' + methodName + '` skips the `constructor` property on prototype objects', 2, function() {
+ test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 2, function() {
function Foo() {}
Foo.prototype.a = 1;
- var expected = ['a'];
- deepEqual(func(Foo.prototype), ['a']);
-
- Foo.prototype = { 'constructor': Foo, 'a': 1 };
- deepEqual(func(Foo.prototype), ['a']);
+ deepEqual(_.keys(Foo.prototype), ['a']);
+ deepEqual(_.keys(shadowedObject).sort(), shadowedProps);
});
- test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties', 1, function() {
- function Foo() {
- this.a = 1;
- this.b = 2;
- }
+ test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', 2, function() {
+ function Foo() {}
Foo.prototype.c = 3;
- var expected = isKeys ? ['a', 'b'] : ['a', 'b', 'c'],
- actual = func(new Foo);
+ Foo.a = 1;
+ Foo.b = 2;
- deepEqual(actual.sort(), expected);
+ var expected = ['a', 'b'];
+ deepEqual(_.keys(Foo), expected);
+
+ Foo.prototype = { 'c': 3 };
+ deepEqual(_.keys(Foo), expected);
});
- });
+ }(1, 2, 3));
/*--------------------------------------------------------------------------*/
@@ -5595,33 +4947,21 @@
];
test('should return the last element', 1, function() {
- strictEqual(_.last(array), 3);
+ equal(_.last(array), 3);
});
test('should return the last two elements', 1, function() {
deepEqual(_.last(array, 2), [2, 3]);
});
- test('should treat falsey `n` values, except nullish, as `0`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return value == null ? 3 : [];
- });
-
- var actual = _.map(falsey, function(n) {
- return _.last(array, n);
- });
-
- deepEqual(actual, expected);
- });
-
test('should return an empty array when `n` < `1`', 3, function() {
- _.each([0, -1, -Infinity], function(n) {
+ _.forEach([0, -1, -2], function(n) {
deepEqual(_.last(array, n), []);
});
});
- test('should return all elements when `n` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
+ test('should return all elements when `n` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(n) {
deepEqual(_.last(array, n), array);
});
});
@@ -5689,7 +5029,7 @@
test('should not chain when arguments are not provided', 1, function() {
if (!isNpm) {
var actual = _(array).last();
- strictEqual(actual, 3);
+ equal(actual, 3);
}
else {
skipTest();
@@ -5713,50 +5053,37 @@
var array = [1, 2, 3, 1, 2, 3];
test('should return the index of the last matched value', 1, function() {
- strictEqual(_.lastIndexOf(array, 3), 5);
+ equal(_.lastIndexOf(array, 3), 5);
});
test('should return `-1` for an unmatched value', 1, function() {
- strictEqual(_.lastIndexOf(array, 4), -1);
+ equal(_.lastIndexOf(array, 4), -1);
});
test('should work with a positive `fromIndex`', 1, function() {
strictEqual(_.lastIndexOf(array, 1, 2), 0);
});
- test('should work with `fromIndex` >= `array.length`', 12, function() {
- _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
- strictEqual(_.lastIndexOf(array, undefined, fromIndex), -1);
- strictEqual(_.lastIndexOf(array, 1, fromIndex), 3);
- strictEqual(_.lastIndexOf(array, '', fromIndex), -1);
+ test('should work with `fromIndex` >= `array.length`', 6, function() {
+ _.forEach([6, 8], function(fromIndex) {
+ equal(_.lastIndexOf(array, undefined, fromIndex), -1);
+ equal(_.lastIndexOf(array, 1, fromIndex), 3);
+ equal(_.lastIndexOf(array, '', fromIndex), -1);
});
});
- test('should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return typeof value == 'number' ? -1 : 5;
- });
-
- var actual = _.map(falsey, function(fromIndex) {
- return _.lastIndexOf(array, 3, fromIndex);
- });
-
- deepEqual(actual, expected);
- });
-
- test('should treat non-number `fromIndex` values as `array.length`', 2, function() {
- strictEqual(_.lastIndexOf(array, 3, '1'), 5);
- strictEqual(_.lastIndexOf(array, 3, true), 5);
- });
-
test('should work with a negative `fromIndex`', 1, function() {
strictEqual(_.lastIndexOf(array, 2, -3), 1);
});
- test('should work with a negative `fromIndex` <= `-array.length`', 3, function() {
- _.each([-6, -8, -Infinity], function(fromIndex) {
- strictEqual(_.lastIndexOf(array, 1, fromIndex), 0);
- });
+ test('should work with a negative `fromIndex` <= `-array.length`', 2, function() {
+ strictEqual(_.lastIndexOf(array, 1, -6), 0);
+ equal(_.lastIndexOf(array, 2, -8), -1);
+ });
+
+ test('should ignore non-number `fromIndex` values', 2, function() {
+ equal(_.lastIndexOf([1, 2, 3], 3, '1'), 2);
+ equal(_.lastIndexOf([1, 2, 3], 3, true), 2);
});
}());
@@ -5765,11 +5092,11 @@
QUnit.module('indexOf methods');
(function() {
- _.each(['indexOf', 'lastIndexOf'], function(methodName) {
+ _.forEach(['indexOf', 'lastIndexOf'], function(methodName) {
var func = _[methodName];
test('`_.' + methodName + '` should accept a falsey `array` argument', 1, function() {
- var expected = _.map(falsey, _.constant(-1));
+ var expected = _.map(falsey, function() { return -1; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -5836,7 +5163,7 @@
test('should return a wrapped value when chaining', 1, function() {
if (!isNpm) {
- ok(_(array).map(_.noop) instanceof _);
+ ok(_(array).map(noop) instanceof _);
}
else {
skipTest();
@@ -5856,8 +5183,8 @@
}
});
- test('should accept a falsey `collection` argument', 1, function() {
- var expected = _.map(falsey, _.constant([]));
+ test('should accept a falsey `array` argument', 1, function() {
+ var expected = _.map(falsey, function() { return []; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -5868,10 +5195,6 @@
deepEqual(actual, expected);
});
- test('should treat number values for `collection` as empty', 1, function() {
- deepEqual(_.map(1), []);
- });
-
test('should be aliased', 1, function() {
strictEqual(_.collect, _.map);
});
@@ -5921,7 +5244,7 @@
test('should return a wrapped value when chaining', 1, function() {
if (!isNpm) {
- ok(_(object).mapValues(_.noop) instanceof _);
+ ok(_(object).mapValues(noop) instanceof _);
}
else {
skipTest();
@@ -5929,7 +5252,7 @@
});
test('should accept a falsey `object` argument', 1, function() {
- var expected = _.map(falsey, _.constant({}));
+ var expected = _.map(falsey, function() { return {}; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -5946,60 +5269,21 @@
QUnit.module('lodash.matches');
(function() {
- var object = { 'a': 1, 'b': 2, 'c': 3 },
- sources = [{ 'a': 1 }, { 'a': 1, 'c': 3 }];
+ var object = { 'a': 1, 'b': 2 };
- test('should create a function that performs a deep comparison between a given object and the `source` object', 6, function() {
- _.each(sources, function(source, index) {
- var matches = _.matches(source);
- strictEqual(matches.length, 1);
- strictEqual(matches(object), true);
+ test('should create a function that performs a deep comparison between a given object and the `source` object', 3, function() {
+ var matches = _.matches({ 'a': 1 });
- matches = _.matches(index ? { 'c': 3, 'd': 4 } : { 'b': 1 });
- strictEqual(matches(object), false);
- });
+ equal(matches.length, 1);
+ strictEqual(matches(object), true);
+
+ matches = _.matches({ 'b': 1 });
+ strictEqual(matches(object), false);
});
- test('should return `true` when comparing an empty `source`', 1, function() {
- var expected = _.map(empties, _.constant(true));
-
- var actual = _.map(empties, function(value) {
- var matches = _.matches(value);
- return matches(object) === true;
- });
-
- deepEqual(actual, expected);
- });
-
- test('should not error error for falsey `object` values', 2, function() {
- var expected = _.map(falsey, _.constant(true));
-
- _.each(sources, function(source) {
- var matches = _.matches(source);
-
- var actual = _.map(falsey, function(value, index) {
- try {
- var result = index ? matches(value) : matches();
- return result === false;
- } catch(e) { }
- });
-
- deepEqual(actual, expected);
- });
- });
-
- test('should return `true` when comparing an empty `source` to a falsey `object`', 1, function() {
- var expected = _.map(falsey, _.constant(true)),
- matches = _.matches({});
-
- var actual = _.map(falsey, function(value, index) {
- try {
- var result = index ? matches(value) : matches();
- return result === true;
- } catch(e) { }
- });
-
- deepEqual(actual, expected);
+ test('should return `false` when comparing an empty `source`', 1, function() {
+ var matches = _.matches({});
+ strictEqual(matches(object), false);
});
}());
@@ -6009,7 +5293,7 @@
(function() {
test('should return the largest value from a collection', 1, function() {
- strictEqual(3, _.max([1, 2, 3]));
+ equal(3, _.max([1, 2, 3]));
});
test('should return `-Infinity` for empty collections', 1, function() {
@@ -6048,16 +5332,16 @@
return a + b + c;
});
- strictEqual(memoized(1, 2, 3), 6);
- strictEqual(memoized(1, 3, 5), 6);
+ equal(memoized(1, 2, 3), 6);
+ equal(memoized(1, 3, 5), 6);
});
test('should support a `resolver` argument', 2, function() {
var fn = function(a, b, c) { return a + b + c; },
memoized = _.memoize(fn, fn);
- strictEqual(memoized(1, 2, 3), 6);
- strictEqual(memoized(1, 3, 5), 9);
+ equal(memoized(1, 2, 3), 6);
+ equal(memoized(1, 3, 5), 9);
});
test('should not set a `this` binding', 2, function() {
@@ -6066,31 +5350,15 @@
});
var object = { 'b': 2, 'c': 3, 'memoized': memoized };
- strictEqual(object.memoized(1), 6);
- strictEqual(object.memoized(2), 7);
- });
-
- test('should throw a TypeError if `resolve` is truthy and not a function', function() {
- raises(function() { _.memoize(_.noop, {}); }, TypeError);
- });
-
- test('should not throw a TypeError if `resolve` is falsey', function() {
- var expected = _.map(falsey, _.constant(true));
-
- var actual = _.map(falsey, function(value, index) {
- try {
- return _.isFunction(index ? _.memoize(_.noop, value) : _.memoize(_.noop));
- } catch(e) { }
- });
-
- deepEqual(actual, expected);
+ equal(object.memoized(1), 6);
+ equal(object.memoized(2), 7);
});
test('should check cache for own properties', 1, function() {
var actual = [],
memoized = _.memoize(_.identity);
- _.each(shadowedProps, function(value) {
+ _.forEach(shadowedProps, function(value) {
actual.push(memoized(value));
});
@@ -6098,14 +5366,14 @@
});
test('should expose a `cache` object on the `memoized` function', 4, function() {
- _.each(['_a', 'a'], function(key, index) {
+ _.forEach(['_a', 'a'], function(key, index) {
var memoized = _.memoize(_.identity, index && _.identity);
memoized('a');
- strictEqual(memoized.cache[key], 'a');
+ equal(memoized.cache[key], 'a');
memoized.cache[key] = 'b';
- strictEqual(memoized('a'), 'b');
+ equal(memoized('a'), 'b');
});
});
}());
@@ -6177,7 +5445,7 @@
};
var actual = _.merge(object, source);
- strictEqual(_.isArguments(actual.args), false);
+ equal(_.isArguments(actual.args), false);
});
test('should work with four arguments', 1, function() {
@@ -6226,7 +5494,7 @@
(function() {
test('should return the smallest value from a collection', 1, function() {
- strictEqual(1, _.min([1, 2, 3]));
+ equal(1, _.min([1, 2, 3]));
});
test('should return `Infinity` for empty collections', 1, function() {
@@ -6259,16 +5527,15 @@
QUnit.module('lodash.max and lodash.min');
- _.each(['max', 'min'], function(methodName) {
+ _.forEach(['max', 'min'], function(methodName) {
var array = [1, 2, 3],
- func = _[methodName],
- isMax = methodName == 'max';
+ func = _[methodName];
test('`_.' + methodName + '` should work with Date objects', 1, function() {
var now = new Date,
past = new Date(0);
- strictEqual(func([now, past]), isMax ? now : past);
+ equal(func([now, past]), methodName == 'max' ? now : past);
});
test('`_.' + methodName + '` should work with a callback argument', 1, function() {
@@ -6276,7 +5543,7 @@
return -num;
});
- strictEqual(actual, isMax ? 1 : 3);
+ equal(actual, methodName == 'max' ? 1 : 3);
});
test('`_.' + methodName + '` should pass the correct `callback` arguments when iterating an array', 1, function() {
@@ -6310,39 +5577,29 @@
return -this[index];
}, array);
- strictEqual(actual, isMax ? 1 : 3);
+ equal(actual, methodName == 'max' ? 1 : 3);
});
test('`_.' + methodName + '` should work when used as a callback for `_.map`', 1, function() {
var array = [[2, 3, 1], [5, 6, 4], [8, 9, 7]],
actual = _.map(array, func);
- deepEqual(actual, isMax ? [3, 6, 9] : [1, 4, 7]);
+ deepEqual(actual, methodName == 'max' ? [3, 6, 9] : [1, 4, 7]);
});
test('`_.' + methodName + '` should iterate an object', 1, function() {
var actual = func({ 'a': 1, 'b': 2, 'c': 3 });
- strictEqual(actual, isMax ? 3 : 1);
+ equal(actual, methodName == 'max' ? 3 : 1);
});
test('`_.' + methodName + '` should iterate a string', 2, function() {
- _.each(['abc', Object('abc')], function(value) {
+ _.forEach(['abc', Object('abc')], function(value) {
var actual = func(value);
- strictEqual(actual, isMax ? 'c' : 'a');
+ equal(actual, methodName == 'max' ? 'c' : 'a');
});
});
- test('`_.' + methodName + '` should work when `callback` returns +/-Infinity', 1, function() {
- var object = { 'a': (isMax ? -Infinity : Infinity) };
-
- var actual = func([object, { 'a': object.a }], function(object) {
- return object.a;
- });
-
- strictEqual(actual, object);
- });
-
- test('`_.' + methodName + '` should work when chaining on an array with only one value', 1, function() {
+ test('`_.' + methodName + '` should resolve the correct value when provided an array containing only one value', 1, function() {
if (!isNpm) {
var actual = _([40])[methodName]().value();
strictEqual(actual, 40);
@@ -6354,7 +5611,7 @@
test('`_.' + methodName + '` should work with extremely large arrays', 1, function() {
var array = _.range(0, 5e5);
- strictEqual(func(array), isMax ? 499999 : 0);
+ equal(func(array), methodName == 'max' ? 499999 : 0);
});
});
@@ -6371,36 +5628,15 @@
}
var value = ['a'],
- source = { 'a': function(array) { return array[0]; }, 'b': 'B' };
-
- test('should use `this` as the default `object` value', 3, function() {
- var object = _.create(_);
- object.mixin(source);
-
- strictEqual(object.a(value), 'a');
-
- ok(!('a' in _));
- ok(!('a' in _.prototype));
-
- delete wrapper.a;
- delete wrapper.prototype.a;
- delete wrapper.b;
- delete wrapper.prototype.b;
- });
+ source = { 'a': function(array) { return array[0]; } };
test('should accept an `object` argument', 1, function() {
- var object = {};
- _.mixin(object, source);
- strictEqual(object.a(value), 'a');
+ var lodash = {};
+ _.mixin(lodash, source);
+ strictEqual(lodash.a(value), 'a');
});
- test('should return `object`', 2, function() {
- var object = {};
- strictEqual(_.mixin(object, source), object);
- strictEqual(_.mixin(), _);
- });
-
- test('should work with a function for `object`', 2, function() {
+ test('should accept a function `object` argument', 2, function() {
_.mixin(wrapper, source);
var wrapped = wrapper(value),
@@ -6411,24 +5647,30 @@
delete wrapper.a;
delete wrapper.prototype.a;
- delete wrapper.b;
- delete wrapper.prototype.b;
});
test('should mixin `source` methods into lodash', 4, function() {
- _.mixin(source);
+ if (!isNpm) {
+ _.mixin({
+ 'a': 'a',
+ 'A': function(string) { return string.toUpperCase(); }
+ });
- strictEqual(_.a(value), 'a');
- strictEqual(_(value).a().__wrapped__, 'a');
+ equal('a' in _, false);
+ equal('a' in _.prototype, false);
- delete _.a;
- delete _.prototype.a;
+ delete _.a;
+ delete _.prototype.a;
- ok(!('b' in _));
- ok(!('b' in _.prototype));
+ equal(_.A('a'), 'A');
+ equal(_('a').A().value(), 'A');
- delete _.b;
- delete _.prototype.b;
+ delete _.A;
+ delete _.prototype.A;
+ }
+ else {
+ skipTest(4);
+ }
});
test('should accept an `options` argument', 16, function() {
@@ -6436,8 +5678,8 @@
return (func === _ ? 'lodash' : 'provided') + ' function should ' + (chain ? '' : 'not ') + 'chain';
}
- _.each([_, wrapper], function(func) {
- _.each([false, true, { 'chain': false }, { 'chain': true }], function(options) {
+ _.forEach([_, wrapper], function(func) {
+ _.forEach([false, true, { 'chain': false }, { 'chain': true }], function(options) {
if (func === _) {
_.mixin(source, options);
} else {
@@ -6446,17 +5688,15 @@
var wrapped = func(value),
actual = wrapped.a();
- if (options === true || (options && options.chain)) {
+ if (options && (options === true || options.chain)) {
strictEqual(actual.__wrapped__, 'a', message(func, true));
ok(actual instanceof func, message(func, true));
} else {
strictEqual(actual, 'a', message(func, false));
- ok(!(actual instanceof func), message(func, false));
+ equal(actual instanceof func, false, message(func, false));
}
delete func.a;
delete func.prototype.a;
- delete func.b;
- delete func.prototype.b;
});
});
});
@@ -6480,36 +5720,9 @@
}
delete _.a;
delete _.prototype.a;
- delete _.b;
- delete _.prototype.b;
ok(pass);
});
-
- test('should return the existing wrapper when chaining', 2, function() {
- if (!isNpm) {
- _.each([_, wrapper], function(func) {
- if (func === _) {
- var wrapper = _(source),
- actual = wrapper.mixin();
-
- strictEqual(actual.value(), _);
- }
- else {
- wrapper = _(func);
- actual = wrapper.mixin(source);
- strictEqual(actual, wrapper);
- }
- delete func.a;
- delete func.prototype.a;
- delete func.b;
- delete func.prototype.b;
- });
- }
- else {
- skipTest(2);
- }
- });
}());
/*--------------------------------------------------------------------------*/
@@ -6519,7 +5732,7 @@
(function() {
test('should always return `undefined`', 1, function() {
var values = falsey.concat([], true, new Date, _, {}, /x/, 'a'),
- expected = _.map(values, _.constant());
+ expected = _.map(values, function() { return undefined; });
var actual = _.map(values, function(value, index) {
return index ? _.noop(value) : _.noop();
@@ -6634,16 +5847,16 @@
(function() {
test('should execute `func` once', 1, function() {
var count = 0,
- once = _.once(function() { count++; });
+ func = _.once(function() { count++; });
- once();
- once();
+ func();
+ func();
strictEqual(count, 1);
});
test('should not set a `this` binding', 1, function() {
- var once = _.once(function() { this.count++; }),
- object = { 'count': 0, 'once': once };
+ var func = _.once(function() { this.count++; }),
+ object = { 'count': 0, 'once': func };
object.once();
object.once();
@@ -6653,26 +5866,26 @@
test('should ignore recursive calls', 1, function() {
var count = 0;
- var once = _.once(function() {
+ var func = _.once(function() {
count++;
- once();
+ func();
});
- once();
+ func();
strictEqual(count, 1);
});
test('should not throw more than once', 2, function() {
- var once = _.once(function() {
+ var pass = true;
+
+ var func = _.once(function() {
throw new Error;
});
- raises(function() { once(); }, Error);
-
- var pass = true;
+ raises(function() { func(); }, Error);
try {
- once();
+ func();
} catch(e) {
pass = false;
}
@@ -6682,104 +5895,6 @@
/*--------------------------------------------------------------------------*/
- QUnit.module('lodash.pad');
-
- (function() {
- test('should pad a string to a given length', 1, function() {
- strictEqual(_.pad('abc', 9), ' abc ');
- });
-
- test('should truncate pad characters to fit the pad length', 2, function() {
- strictEqual(_.pad('abc', 8), ' abc ');
- strictEqual(_.pad('abc', 8, '_-'), '_-abc_-_');
- });
-
- test('should coerce `string` to a string', 2, function() {
- strictEqual(_.pad(Object('abc'), 4), 'abc ');
- strictEqual(_.pad({ 'toString': _.constant('abc') }, 5), ' abc ');
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.padLeft');
-
- (function() {
- test('should pad a string to a given length', 1, function() {
- strictEqual(_.padLeft('abc', 6), ' abc');
- });
-
- test('should truncate pad characters to fit the pad length', 1, function() {
- strictEqual(_.padLeft('abc', 6, '_-'), '_-_abc');
- });
-
- test('should coerce `string` to a string', 2, function() {
- strictEqual(_.padLeft(Object('abc'), 4), ' abc');
- strictEqual(_.padLeft({ 'toString': _.constant('abc') }, 5), ' abc');
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.padRight');
-
- (function() {
- test('should pad a string to a given length', 1, function() {
- strictEqual(_.padRight('abc', 6), 'abc ');
- });
-
- test('should truncate pad characters to fit the pad length', 1, function() {
- strictEqual(_.padRight('abc', 6, '_-'), 'abc_-_');
- });
-
- test('should coerce `string` to a string', 2, function() {
- strictEqual(_.padRight(Object('abc'), 4), 'abc ');
- strictEqual(_.padRight({ 'toString': _.constant('abc') }, 5), 'abc ');
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('pad methods');
-
- _.each(['pad', 'padLeft', 'padRight'], function(methodName, index) {
- var func = _[methodName];
-
- test('`_.' + methodName + '` should not pad is string is >= `length`', 2, function() {
- strictEqual(func('abc', 2), 'abc');
- strictEqual(func('abc', 3), 'abc');
- });
-
- test('`_.' + methodName + '` should treat negative `length` as `0`', 2, function() {
- _.each([0, -2], function(length) {
- strictEqual(func('abc', length), 'abc');
- });
- });
-
- test('`_.' + methodName + '` should coerce `length` to a number', 2, function() {
- _.each(['', '4'], function(length) {
- var actual = length ? (index == 1 ? ' abc' : 'abc ') : 'abc';
- strictEqual(func('abc', length), actual);
- });
- });
-
- test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string and `chars`', 6, function() {
- _.each([null, '_-'], function(chars) {
- strictEqual(func(null, 0, chars), '');
- strictEqual(func(undefined, 0, chars), '');
- strictEqual(func('', 0, chars), '');
- });
- });
-
- test('`_.' + methodName + '` should work with `null`, `undefined`, or empty string for `chars`', 3, function() {
- notStrictEqual(func('abc', 6, null), 'abc');
- notStrictEqual(func('abc', 6, undefined), 'abc');
- strictEqual(func('abc', 6, ''), 'abc');
- });
- });
-
- /*--------------------------------------------------------------------------*/
-
QUnit.module('lodash.pairs');
(function() {
@@ -6817,7 +5932,7 @@
});
test('should use a radix of `16`, for hexadecimals, if `radix` is `undefined` or `0`', 8, function() {
- _.each(['0x20', '0X20'], function(string) {
+ _.forEach(['0x20', '0X20'], function(string) {
strictEqual(_.parseInt(string), 32);
strictEqual(_.parseInt(string, 0), 32);
strictEqual(_.parseInt(string, 16), 32);
@@ -6837,7 +5952,7 @@
strictEqual(_.parseInt(whitespace + '08'), 8);
strictEqual(_.parseInt(whitespace + '08', 10), 8);
- _.each(['0x20', '0X20'], function(string) {
+ _.forEach(['0x20', '0X20'], function(string) {
strictEqual(_.parseInt(whitespace + string), 32);
strictEqual(_.parseInt(whitespace + string, 16), 32);
});
@@ -6854,13 +5969,15 @@
QUnit.module('partial methods');
- _.each(['partial', 'partialRight'], function(methodName) {
+ _.forEach(['partial', 'partialRight'], function(methodName) {
var func = _[methodName],
isPartial = methodName == 'partial';
test('`_.' + methodName + '` partially applies arguments', 1, function() {
- var par = func(_.identity, 'a');
- strictEqual(par(), 'a');
+ var fn = function(a) { return a; },
+ par = func(fn, 'a');
+
+ equal(par(), 'a');
});
test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() {
@@ -6879,29 +5996,10 @@
});
test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked with additional arguments', 1, function() {
- var par = func(_.identity);
- strictEqual(par('a'), 'a');
- });
+ var fn = function(a) { return a; },
+ par = func(fn);
- test('`_.' + methodName + '` should support placeholders', 4, function() {
- if (!isModularize) {
- var fn = function() { return slice.call(arguments); },
- par = func(fn, _, 'b', _);
-
- deepEqual(par('a', 'c'), ['a', 'b', 'c']);
- deepEqual(par('a'), ['a', 'b', undefined]);
- deepEqual(par(), [undefined, 'b', undefined]);
-
- if (isPartial) {
- deepEqual(par('a', 'c', 'd'), ['a', 'b', 'c', 'd']);
- } else {
- par = func(fn, _, 'c', _);
- deepEqual(par('a', 'b', 'd'), ['a', 'b', 'c', 'd']);
- }
- }
- else {
- skipTest(4);
- }
+ equal(par('a'), 'a');
});
test('`_.' + methodName + '` should not alter the `this` binding', 3, function() {
@@ -6929,14 +6027,36 @@
function Foo(value) {
return value && object;
}
-
- var object = {},
- par = func(Foo);
+ var par = func(Foo),
+ object = {};
ok(new par instanceof Foo);
strictEqual(new par(true), object);
});
+ test('`_.' + methodName + '` should support placeholders', 4, function() {
+ if (_._iteratorTemplate) {
+ var fn = function() {
+ return slice.call(arguments);
+ };
+
+ var par = func(fn, _, 'b', _);
+ deepEqual(par('a', 'c'), ['a', 'b', 'c']);
+ deepEqual(par('a'), ['a', 'b', undefined]);
+ deepEqual(par(), [undefined, 'b', undefined]);
+
+ if (isPartial) {
+ deepEqual(par('a', 'c', 'd'), ['a', 'b', 'c', 'd']);
+ } else {
+ par = func(fn, _, 'c', _);
+ deepEqual(par('a', 'b', 'd'), ['a', 'b', 'c', 'd']);
+ }
+ }
+ else {
+ skipTest(4);
+ }
+ });
+
test('`_.' + methodName + '` should clone metadata for created functions', 3, function() {
var greet = function(greeting, name) {
return greeting + ' ' + name;
@@ -6946,17 +6066,17 @@
par2 = func(par1, 'barney'),
par3 = func(par1, 'pebbles');
- strictEqual(par1('fred'), isPartial ? 'hi fred' : 'fred hi')
- strictEqual(par2(), isPartial ? 'hi barney' : 'barney hi');
- strictEqual(par3(), isPartial ? 'hi pebbles' : 'pebbles hi');
+ equal(par1('fred'), isPartial ? 'hi fred' : 'fred hi')
+ equal(par2(), isPartial ? 'hi barney' : 'barney hi');
+ equal(par3(), isPartial ? 'hi pebbles' : 'pebbles hi');
});
test('`_.' + methodName + '` should work with curried methods', 2, function() {
var fn = function(a, b, c) { return a + b + c; },
curried = _.curry(func(fn, 1), 2);
- strictEqual(curried(2, 3), 6);
- strictEqual(curried(2)(3), 6);
+ equal(curried(2, 3), 6);
+ equal(curried(2)(3), 6);
});
});
@@ -6981,9 +6101,9 @@
(function() {
test('combinations of partial functions should work', 1, function() {
- function fn() {
+ var fn = function() {
return slice.call(arguments);
- }
+ };
var a = _.partial(fn),
b = _.partialRight(a, 3),
@@ -6993,11 +6113,11 @@
});
test('combinations of bound and partial functions should work', 3, function() {
- function fn() {
+ var fn = function() {
var result = [this.a];
push.apply(result, arguments);
return result;
- }
+ };
var expected = [1, 2, 3, 4],
object = { 'a': 1, 'fn': fn };
@@ -7022,9 +6142,9 @@
});
test('recursively bound functions should work', 1, function() {
- function fn() {
+ var fn = function() {
return this.a;
- }
+ };
var a = _.bind(fn, { 'a': 1 }),
b = _.bind(a, { 'a': 2 }),
@@ -7042,9 +6162,9 @@
var array = [1, 0, 1];
test('should always return two groups of elements', 3, function() {
- deepEqual(_.partition([], _.identity), [[], []]);
- deepEqual(_.partition(array, _.constant(true)), [array, []]);
- deepEqual(_.partition(array, _.constant(false)), [[], array]);
+ deepEqual(_.partition([], function(value) { return value; }), [[], []]);
+ deepEqual(_.partition(array, function(value) { return true; }), [array, []]);
+ deepEqual(_.partition(array, function(value) { return false; }), [[], array]);
});
test('should use `_.identity` when no `callback` is provided', 1, function() {
@@ -7187,25 +6307,6 @@
var object = { 'a': [1], 'b': [1, 2], 'c': [1, 2, 3] };
deepEqual(_.pluck(object, 'length'), [1, 2, 3]);
});
-
- test('should work with nullish elements', 1, function() {
- var objects = [{ 'a': 1 }, null, undefined, { 'a': 4 }];
- deepEqual(_.pluck(objects, 'a'), [1, undefined, undefined, 4]);
- });
-
- test('should coerce `key` to a string', 1, function() {
- function fn() {}
- fn.toString = _.constant('fn');
-
- var objects = [{ 'null': 1 }, { 'undefined': 2 }, { 'fn': 3 }, { '[object Object]': 4 }],
- values = [null, undefined, fn, {}]
-
- var actual = _.map(objects, function(object, index) {
- return _.pluck([object], values[index]);
- });
-
- deepEqual(actual, [[1], [2], [3], [4]]);
- });
}());
/*--------------------------------------------------------------------------*/
@@ -7217,10 +6318,10 @@
var object = { 'a': 1, 'b': 2 },
property = _.property('a');
- strictEqual(property.length, 1);
+ equal(property.length, 1);
strictEqual(property(object), 1);
- property = _.property('b');
+ property = _.property('b');
strictEqual(property(object), 2);
});
@@ -7228,7 +6329,7 @@
var array = [1, 2, 3],
property = _.property(1);
- strictEqual(property(array), 2);
+ equal(property(array), 2);
});
}());
@@ -7251,8 +6352,8 @@
delete array[3];
_.pull(array, 1);
- ok(!('0' in array));
- ok(!('2' in array));
+ equal(0 in array, false);
+ equal(2 in array, false);
});
test('should treat holes as `undefined`', 1, function() {
@@ -7281,7 +6382,7 @@
test('supports not passing a `max` argument', 1, function() {
ok(_.some(array, function() {
- return _.random(5) !== 5;
+ return _.random(5) != 5;
}));
});
@@ -7328,6 +6429,8 @@
QUnit.module('lodash.range');
(function() {
+ var func = _.range;
+
test('should work when passing a single `end` argument', 1, function() {
deepEqual(_.range(4), [0, 1, 2, 3]);
});
@@ -7354,7 +6457,7 @@
});
test('should treat falsey `start` arguments as `0`', 13, function() {
- _.each(falsey, function(value, index) {
+ _.forEach(falsey, function(value, index) {
if (index) {
deepEqual(_.range(value), []);
deepEqual(_.range(value, 1), [0]);
@@ -7364,9 +6467,9 @@
});
});
- test('should coerce arguments to finite numbers', 1, function() {
- var actual = [_.range('0', 1), _.range('1'), _.range(0, 1, '1'), _.range(NaN), _.range(NaN, NaN)];
- deepEqual(actual, [[0], [0], [0], [], []]);
+ test('should coerce arguments to numbers', 1, function() {
+ var actual = [func('0',1), func('1'), func(0, 1, '1')];
+ deepEqual(actual, [[0], [0], [0]]);
});
}());
@@ -7425,7 +6528,7 @@
deepEqual(args, expected);
});
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -7439,7 +6542,7 @@
});
deepEqual(args, ['a', 'b', 1, collection]);
- strictEqual(actual, 'abc');
+ equal(actual, 'abc');
});
});
@@ -7457,7 +6560,7 @@
var array = [1, 2, 3];
test('should use the last element of a collection as the default `accumulator`', 1, function() {
- strictEqual(_.reduceRight(array), 3);
+ equal(_.reduceRight(array), 3);
});
test('should pass the correct `callback` arguments when iterating an array', 2, function() {
@@ -7504,7 +6607,7 @@
deepEqual(args, expected);
});
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -7518,7 +6621,7 @@
});
deepEqual(args, ['c', 'b', 1, collection]);
- strictEqual(actual, 'cba');
+ equal(actual, 'cba');
});
});
@@ -7531,7 +6634,7 @@
QUnit.module('reduce methods');
- _.each(['reduce', 'reduceRight'], function(methodName) {
+ _.forEach(['reduce', 'reduceRight'], function(methodName) {
var array = [1, 2, 3],
func = _[methodName];
@@ -7540,7 +6643,7 @@
return accumulator + value;
}, '');
- strictEqual(actual, methodName == 'reduce' ? 'abc' : 'cba');
+ equal(actual, methodName == 'reduce' ? 'abc' : 'cba');
});
test('`_.' + methodName + '` should support the `thisArg` argument', 1, function() {
@@ -7557,7 +6660,7 @@
return sum + num;
});
- strictEqual(actual, 6);
+ equal(actual, 6);
}
else {
skipTest();
@@ -7566,11 +6669,11 @@
test('`_.' + methodName + '` should support empty or falsey collections without an initial `accumulator` value', 1, function() {
var actual = [],
- expected = _.map(empties, _.constant());
+ expected = _.map(empties, function() { return undefined; });
- _.each(empties, function(value) {
+ _.forEach(empties, function(value) {
try {
- actual.push(func(value, _.noop));
+ actual.push(func(value, noop));
} catch(e) { }
});
@@ -7578,11 +6681,11 @@
});
test('`_.' + methodName + '` should support empty or falsey collections with an initial `accumulator` value', 1, function() {
- var expected = _.map(empties, _.constant('x'));
+ var expected = _.map(empties, function() { return 'x'; });
var actual = _.map(empties, function(value) {
try {
- return func(value, _.noop, 'x');
+ return func(value, noop, 'x');
} catch(e) { }
});
@@ -7590,7 +6693,7 @@
});
test('`_.' + methodName + '` should handle an initial `accumulator` value of `undefined`', 1, function() {
- var actual = func([], _.noop, undefined);
+ var actual = func([], noop, undefined);
strictEqual(actual, undefined);
});
@@ -7600,12 +6703,12 @@
if ('__proto__' in array) {
array.__proto__ = object;
- strictEqual(_.reduce(array, _.noop), undefined);
+ strictEqual(_.reduce(array, noop), undefined);
}
else {
skipTest();
}
- strictEqual(_.reduce(object, _.noop), undefined);
+ strictEqual(_.reduce(object, noop), undefined);
});
});
@@ -7627,7 +6730,7 @@
QUnit.module('filter methods');
- _.each(['filter', 'reject'], function(methodNames) {
+ _.forEach(['filter', 'reject'], function(methodNames) {
var func = _[methodNames];
test('`_.' + methodNames + '` should not modify the resulting value from within `callback`', 1, function() {
@@ -7683,8 +6786,8 @@
delete array[3];
_.remove(array, function(num) { return num === 1; });
- ok(!('0' in array));
- ok(!('2' in array));
+ equal(0 in array, false);
+ equal(2 in array, false);
});
test('should treat holes as `undefined`', 1, function() {
@@ -7698,28 +6801,55 @@
/*--------------------------------------------------------------------------*/
- QUnit.module('lodash.repeat');
+ QUnit.module('lodash.removeAt');
(function() {
- test('should repeat a string `n` times', 2, function() {
- strictEqual(_.repeat('*', 3), '***');
- strictEqual(_.repeat('abc', 2), 'abcabc');
+ test('should modify the array and return removed elements', 2, function() {
+ var array = [1, 2, 3];
+ var actual = _.removeAt(array, [0, 1]);
+
+ deepEqual(array, [3]);
+ deepEqual(actual, [1, 2]);
});
- test('should return an empty string for negative `n` or `n` of `0`', 2, function() {
- strictEqual(_.repeat('abc', 0), '');
- strictEqual(_.repeat('abc', -2), '');
+ test('should work with unsorted indexes', 2, function() {
+ var array = [1, 2, 3, 4, 5];
+ var actual = _.removeAt(array, [4, 1, 0, 3]);
+
+ deepEqual(array, [3]);
+ deepEqual(actual, [1, 2, 4, 5]);
});
- test('should coerce `n` to a number', 3, function() {
- strictEqual(_.repeat('abc'), '');
- strictEqual(_.repeat('abc', '2'), 'abcabc');
- strictEqual(_.repeat('*', { 'valueOf': _.constant(3) }), '***');
+ test('should return `undefined` for nonexistent keys', 2, function() {
+ var array = ['a', 'b', 'c'];
+ var actual = _.removeAt(array, [0, 2, 4]);
+
+ deepEqual(array, ['b']);
+ deepEqual(actual, ['a', 'c', undefined]);
});
- test('should coerce `string` to a string', 2, function() {
- strictEqual(_.repeat(Object('abc'), 2), 'abcabc');
- strictEqual(_.repeat({ 'toString': _.constant('*') }, 3), '***');
+ test('should return an empty array when no keys are provided', 2, function() {
+ var array = ['a', 'b', 'c'];
+ var actual = _.removeAt(array);
+
+ deepEqual(array, ['a', 'b', 'c']);
+ deepEqual(actual, []);
+ });
+
+ test('should accept multiple index arguments', 2, function() {
+ var array = ['a', 'b', 'c', 'd'];
+ var actual = _.removeAt(array, 0, 2, 3);
+
+ deepEqual(array, ['b']);
+ deepEqual(actual, ['a', 'c', 'd']);
+ });
+
+ test('should work when used as a callback for `_.map`', 2, function() {
+ var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
+ var actual = _.map(array, _.removeAt);
+
+ deepEqual(array, [[2, 3], [4, 6], [7, 8]]);
+ deepEqual(actual, [[1], [5], [9]]);
});
}());
@@ -7741,13 +6871,13 @@
strictEqual(_.result(object, 'd'), undefined);
});
- test('should return `undefined` when `object` is nullish', 2, function() {
+ test('should return `undefined` when `object` is `null` or `undefined`', 2, function() {
strictEqual(_.result(null, 'a'), undefined);
strictEqual(_.result(undefined, 'a'), undefined);
});
test('should return the specified default value for undefined properties', 1, function() {
- var values = falsey.concat(1, _.constant(1));
+ var values = falsey.concat(1, function() { return 1; });
var expected = _.transform(values, function(result, value) {
result.push(value, value);
@@ -7778,7 +6908,7 @@
];
test('should accept a falsey `array` argument', 1, function() {
- var expected = _.map(falsey, _.constant([]));
+ var expected = _.map(falsey, function() { return []; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -7797,26 +6927,14 @@
deepEqual(_.rest(array, 2), [3]);
});
- test('should treat falsey `n` values, except nullish, as `0`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return value == null ? [2, 3] : array;
- });
-
- var actual = _.map(falsey, function(n) {
- return _.rest(array, n);
- });
-
- deepEqual(actual, expected);
- });
-
test('should return all elements when `n` < `1`', 3, function() {
- _.each([0, -1, -Infinity], function(n) {
- deepEqual(_.rest(array, n), array);
+ _.forEach([0, -1, -2], function(n) {
+ deepEqual(_.rest(array, n), [1, 2, 3]);
});
});
- test('should return an empty array when `n` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
+ test('should return an empty array when `n` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(n) {
deepEqual(_.rest(array, n), []);
});
});
@@ -7850,7 +6968,7 @@
deepEqual(args, [1, 0, array]);
});
- test('should support the `thisArg` argument', 1, function() {
+ test('supports the `thisArg` argument', 1, function() {
var actual = _.rest(array, function(num, index) {
return this[index] < 3;
}, array);
@@ -7917,26 +7035,14 @@
deepEqual(actual.sort(), array);
});
- test('should treat falsey `n` values, except nullish, as `0`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return value == null ? 1 : [];
- });
-
- var actual = _.map(falsey, function(n) {
- return _.sample([1], n);
- });
-
- deepEqual(actual, expected);
- });
-
- test('should return an empty array when `n` < `1` or `NaN`', 3, function() {
- _.each([0, -1, -Infinity], function(n) {
+ test('should return an empty array when `n` < `1`', 3, function() {
+ _.forEach([0, -1, -2], function(n) {
deepEqual(_.sample(array, n), []);
});
});
- test('should return all elements when `n` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
+ test('should return all elements when `n` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(n) {
deepEqual(_.sample(array, n).sort(), array);
});
});
@@ -7952,7 +7058,7 @@
result.push([], []);
});
- _.each(empties, function(value) {
+ _.forEach(empties, function(value) {
try {
actual.push(_.shuffle(value), _.shuffle(value, 1));
} catch(e) { }
@@ -8000,7 +7106,7 @@
}
});
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -8037,11 +7143,7 @@
deepEqual(actual.sort(), array);
});
- test('should treat number values for `collection` as empty', 1, function() {
- deepEqual(_.shuffle(1), []);
- });
-
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -8062,15 +7164,15 @@
array = [1, 2, 3];
test('should return the number of own enumerable properties of an object', 1, function() {
- strictEqual(_.size({ 'one': 1, 'two': 2, 'three': 3 }), 3);
+ equal(_.size({ 'one': 1, 'two': 2, 'three': 3 }), 3);
});
test('should return the length of an array', 1, function() {
- strictEqual(_.size(array), 3);
+ equal(_.size(array), 3);
});
test('should accept a falsey `object` argument', 1, function() {
- var expected = _.map(falsey, _.constant(0));
+ var expected = _.map(falsey, function() { return 0; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -8081,34 +7183,26 @@
deepEqual(actual, expected);
});
- test('should work with `arguments` objects (test in IE < 9)', 1, function() {
- strictEqual(_.size(args), 3);
- });
-
test('should work with jQuery/MooTools DOM query collections', 1, function() {
function Foo(elements) { push.apply(this, elements); }
Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice };
- strictEqual(_.size(new Foo(array)), 3);
+ equal(_.size(new Foo(array)), 3);
});
- test('should not treat objects with negative lengths as array-like', 1, function() {
- strictEqual(_.size({ 'length': -1 }), 1);
+ test('should work with `arguments` objects (test in IE < 9)', 1, function() {
+ if (!isPhantomPage) {
+ equal(_.size(args), 3);
+ } else {
+ skipTest();
+ }
});
- test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() {
- strictEqual(_.size({ 'length': maxSafeInteger + 1 }), 1);
+ test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() {
+ equal(_.size(shadowedObject), 7);
});
- test('should not treat objects with non-number lengths as array-like', 1, function() {
- strictEqual(_.size({ 'length': '0' }), 1);
- });
-
- test('fixes the JScript `[[DontEnum]]` bug (test in IE < 9)', 1, function() {
- strictEqual(_.size(shadowedObject), 7);
- });
-
- _.each({
+ _.forEach({
'literal': 'abc',
'object': Object('abc')
},
@@ -8130,28 +7224,18 @@
deepEqual(_.slice(array, 1), [2, 3]);
});
- test('should work with a `start` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(start) {
+ test('should work with a `start` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(start) {
deepEqual(_.slice(array, start), []);
});
});
- test('should treat falsey `start` values as `0`', 1, function() {
- var expected = _.map(falsey, _.constant(array));
-
- var actual = _.map(falsey, function(start) {
- return _.slice(array, start);
- });
-
- deepEqual(actual, expected);
- });
-
test('should work with a negative `start`', 1, function() {
deepEqual(_.slice(array, -1), [3]);
});
- test('should work with a negative `start` <= negative `array.length`', 3, function() {
- _.each([-3, -4, -Infinity], function(start) {
+ test('should work with a negative `start` <= negative `array.length`', 2, function() {
+ _.forEach([-3, -4], function(start) {
deepEqual(_.slice(array, start), [1, 2, 3]);
});
});
@@ -8160,38 +7244,21 @@
deepEqual(_.slice(array, 0, 1), [1]);
});
- test('should work with a `end` >= `array.length`', 4, function() {
- _.each([3, 4, Math.pow(2, 32), Infinity], function(end) {
+ test('should work with a `end` >= `array.length`', 2, function() {
+ _.forEach([3, 4], function(end) {
deepEqual(_.slice(array, 0, end), [1, 2, 3]);
});
});
- test('should treat falsey `end` values, except `undefined`, as `0`', 1, function() {
- var expected = _.map(falsey, function(value) {
- return value === undefined ? array : [];
- });
-
- var actual = _.map(falsey, function(end) {
- return _.slice(array, 0, end);
- });
-
- deepEqual(actual, expected);
- });
-
test('should work with a negative `end`', 1, function() {
deepEqual(_.slice(array, 0, -1), [1, 2]);
});
- test('should work with a negative `end` <= negative `array.length`', 3, function() {
- _.each([-3, -4, -Infinity], function(end) {
+ test('should work with a negative `end` <= negative `array.length`', 2, function() {
+ _.forEach([-3, -4], function(end) {
deepEqual(_.slice(array, 0, end), []);
});
});
-
- test('should coerce `start` and `end` to finite numbers', 1, function() {
- var actual = [_.slice(array, '0', 1), _.slice(array, 0, '1'), _.slice(array, '1'), _.slice(array, NaN, 1), _.slice(array, 1, NaN)];
- deepEqual(actual, [[1], [1], [2, 3], [1], []]);
- });
}());
/*--------------------------------------------------------------------------*/
@@ -8200,7 +7267,7 @@
(function() {
test('should return `false` for empty or falsey collections', 1, function() {
- var expected = _.map(empties, _.constant(false));
+ var expected = _.map(empties, function() { return false; });
var actual = _.map(empties, function(value) {
try {
@@ -8211,7 +7278,7 @@
deepEqual(actual, expected);
});
- test('should return `true` if the callback returns truthy for any element in the collection', 2, function() {
+ test('should return `true` if the callback returns truey for any element in the collection', 2, function() {
strictEqual(_.some([false, 1, ''], _.identity), true);
strictEqual(_.some([null, 'x', 0], _.identity), true);
});
@@ -8221,7 +7288,7 @@
strictEqual(_.some([null, 0, ''], _.identity), false);
});
- test('should return `true` as soon as the `callback` result is truthy', 1, function() {
+ test('should return `true` as soon as the `callback` result is truey', 1, function() {
strictEqual(_.some([null, true, null], _.identity), true);
});
@@ -8323,10 +7390,6 @@
deepEqual(actual, [3, 1, 2]);
});
- test('should treat number values for `collection` as empty', 1, function() {
- deepEqual(_.sortBy(1), []);
- });
-
test('should support sorting by an array of properties', 1, function() {
var actual = _.sortBy(objects, ['a', 'b']);
deepEqual(actual, [objects[2], objects[0], objects[3], objects[1]]);
@@ -8357,8 +7420,8 @@
objects = [{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }];
test('should return the insert index of a given value', 2, function() {
- strictEqual(_.sortedIndex(array, 40), 2);
- strictEqual(_.sortedIndex(array, 30), 1);
+ equal(_.sortedIndex(array, 40), 2);
+ equal(_.sortedIndex(array, 30), 1);
});
test('should pass the correct `callback` arguments', 1, function() {
@@ -8381,7 +7444,7 @@
test('should work with a string for `callback`', 1, function() {
var actual = _.sortedIndex(objects, { 'x': 40 }, 'x');
- strictEqual(actual, 2);
+ equal(actual, 2);
});
test('supports arrays with lengths larger than `Math.pow(2, 31) - 1`', 1, function() {
@@ -8393,7 +7456,7 @@
if (array.length == length) {
array[index] = index;
_.sortedIndex(array, index, function() { steps++; });
- strictEqual(steps, 33);
+ equal(steps, 33);
}
else {
skipTest();
@@ -8407,9 +7470,7 @@
(function() {
test('should contain properties with boolean values', 1, function() {
- ok(_.every(_.values(_.support), function(value) {
- return value === true || value === false;
- }));
+ ok(_.every(_.values(_.support), _.isBoolean));
});
test('should not contain minified properties (test production builds)', 1, function() {
@@ -8425,94 +7486,17 @@
'nodeClass',
'nonEnumArgs',
'nonEnumShadows',
- 'nonEnumStrings',
'ownLast',
'spliceObjects',
'unindexedChars'
];
- ok(_.isEmpty(_.difference(_.keys(_.support), props)));
+ ok(!_.size(_.difference(_.keys(_.support), props)));
});
}());
/*--------------------------------------------------------------------------*/
- QUnit.module('lodash.startsWith');
-
- (function() {
- var string = 'abc';
-
- test('should return `true` if a string starts with `target`', 1, function() {
- strictEqual(_.startsWith(string, 'a'), true);
- });
-
- test('should return `false` if a string does not start with `target`', 1, function() {
- strictEqual(_.startsWith(string, 'b'), false);
- });
-
- test('should work with a `position` argument', 1, function() {
- strictEqual(_.startsWith(string, 'b', 1), true);
- });
-
- test('should work with `position` >= `string.length`', 4, function() {
- _.each([3, 5, maxSafeInteger, Infinity], function(position) {
- strictEqual(_.startsWith(string, 'a', position), false);
- });
- });
-
- test('should treat falsey `position` values as `0`', 1, function() {
- var expected = _.map(falsey, _.constant(true));
-
- var actual = _.map(falsey, function(position) {
- return _.startsWith(string, 'a', position);
- });
-
- deepEqual(actual, expected);
- });
-
- test('should treat a negative `position` as `0`', 6, function() {
- _.each([-1, -3, -Infinity], function(position) {
- strictEqual(_.startsWith(string, 'a', position), true);
- strictEqual(_.startsWith(string, 'b', position), false);
- });
- });
-
- test('should always return `true` when `target` is an empty string regardless of `position`', 1, function() {
- ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, maxSafeInteger, Infinity], function(position) {
- return _.startsWith(string, '', position, true);
- }));
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('lodash.startsWith and lodash.endsWith');
-
- _.each(['startsWith', 'endsWith'], function(methodName) {
- var func = _[methodName],
- isEndsWith = methodName == 'endsWith',
- chr = isEndsWith ? 'c' : 'a',
- string = 'abc';
-
- test('`_.' + methodName + '` should coerce `string` to a string', 2, function() {
- strictEqual(func(Object(string), chr), true);
- strictEqual(func({ 'toString': _.constant(string) }, chr), true);
- });
-
- test('`_.' + methodName + '` should coerce `target` to a string', 2, function() {
- strictEqual(func(string, Object(chr)), true);
- strictEqual(func(string, { 'toString': _.constant(chr) }), true);
- });
-
- test('`_.' + methodName + '` should coerce `position` to a number', 2, function() {
- var position = isEndsWith ? 2 : 1;
- strictEqual(func(string, 'b', Object(position)), true);
- strictEqual(func(string, 'b', { 'toString': _.constant(String(position)) }), true);
- });
- });
-
- /*--------------------------------------------------------------------------*/
-
QUnit.module('lodash.tap');
(function() {
@@ -8577,7 +7561,7 @@
unescaped = '&<>"\'\/';
var compiled = _.template('<%- value %>
');
- strictEqual(compiled({ 'value': unescaped }), escaped);
+ equal(compiled({ 'value': unescaped }), escaped);
});
test('should evaluate JavaScript in "evaluate" delimiters', 1, function() {
@@ -8589,24 +7573,24 @@
);
var actual = compiled({ 'collection': { 'a': 'A', 'b': 'B' } });
- strictEqual(actual, '');
+ equal(actual, '');
});
test('should interpolate data object properties', 1, function() {
var compiled = _.template('<%= a %>BC');
- strictEqual(compiled({ 'a': 'A' }), 'ABC');
+ equal(compiled({ 'a': 'A' }), 'ABC');
});
test('should support escaped values in "interpolation" delimiters', 1, function() {
var compiled = _.template('<%= a ? "a=\\"A\\"" : "" %>');
- strictEqual(compiled({ 'a': true }), 'a="A"');
+ equal(compiled({ 'a': true }), 'a="A"');
});
test('should work with "interpolate" delimiters containing ternary operators', 1, function() {
var compiled = _.template('<%= value ? value : "b" %>'),
data = { 'value': 'a' };
- strictEqual(compiled(data), 'a');
+ equal(compiled(data), 'a');
});
test('should work with "interpolate" delimiters containing global values', 1, function() {
@@ -8616,11 +7600,11 @@
var actual = compiled();
} catch(e) { }
- strictEqual(actual, 'function');
+ equal(actual, 'function');
});
test('should work with complex "interpolate" delimiters', 22, function() {
- _.each({
+ _.forEach({
'<%= a + b %>': '3',
'<%= b - a %>': '1',
'<%= a = b %>': '2',
@@ -8648,19 +7632,19 @@
var compiled = _.template(key),
data = { 'a': 1, 'b': 2 };
- strictEqual(compiled(data), value, key);
+ equal(compiled(data), value, key);
});
});
test('should parse ES6 template delimiters', 2, function() {
var data = { 'value': 2 };
strictEqual(_.template('1${value}3', data), '123');
- strictEqual(_.template('${"{" + value + "\\}"}', data), '{2}');
+ equal(_.template('${"{" + value + "\\}"}', data), '{2}');
});
test('should not reference `_.escape` when "escape" delimiters are not used', 1, function() {
var compiled = _.template('<%= typeof __e %>');
- strictEqual(compiled({}), 'undefined');
+ equal(compiled({}), 'undefined');
});
test('should allow referencing variables declared in "evaluate" delimiters from other delimiters', 1, function() {
@@ -8672,7 +7656,7 @@
test('should support single line comments in "evaluate" delimiters (test production builds)', 1, function() {
var compiled = _.template('<% // comment %><% if (value) { %>yap<% } else { %>nope<% } %>');
- strictEqual(compiled({ 'value': true }), 'yap');
+ equal(compiled({ 'value': true }), 'yap');
});
test('should work with custom `_.templateSettings` delimiters', 1, function() {
@@ -8684,10 +7668,10 @@
'interpolate': /\{\{=([\s\S]+?)\}\}/g
});
- var compiled = _.template('{{ _.each(collection, function(value, index) { }}- {{= index }}: {{- value }}
{{ }); }}
'),
+ var compiled = _.template('{{ _.forEach(collection, function(value, index) { }}- {{= index }}: {{- value }}
{{ }); }}
'),
expected = '';
- strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected);
+ equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected);
_.assign(_.templateSettings, settings);
});
@@ -8700,16 +7684,16 @@
'interpolate': /<\?=([\s\S]+?)\?>/g
});
- var compiled = _.template(' _.each(collection, function(value, index) { ?>- = index ?>: - value ?>
}); ?>
'),
+ var compiled = _.template(' _.forEach(collection, function(value, index) { ?>- = index ?>: - value ?>
}); ?>
'),
expected = '';
- strictEqual(compiled({ 'collection': ['a & A', 'b & B'] }), expected);
+ equal(compiled({ 'collection': ['a & A', 'b & B'] }), expected);
_.assign(_.templateSettings, settings);
});
test('should work with no delimiters', 1, function() {
var expected = 'abc';
- strictEqual(_.template(expected, {}), expected);
+ equal(_.template(expected, {}), expected);
});
test('should support the "imports" option', 1, function() {
@@ -8721,7 +7705,7 @@
test('should support the "variable" options', 1, function() {
var compiled = _.template(
- '<% _.each( data.a, function( value ) { %>' +
+ '<% _.forEach( data.a, function( value ) { %>' +
'<%= value.valueOf() %>' +
'<% }) %>', null, { 'variable': 'data' }
);
@@ -8735,32 +7719,32 @@
});
test('should use a `with` statement by default', 1, function() {
- var compiled = _.template('<%= index %><%= collection[index] %><% _.each(collection, function(value, index) { %><%= index %><% }); %>'),
+ var compiled = _.template('<%= index %><%= collection[index] %><% _.forEach(collection, function(value, index) { %><%= index %><% }); %>'),
actual = compiled({ 'index': 1, 'collection': ['a', 'b', 'c'] });
- strictEqual(actual, '1b012');
+ equal(actual, '1b012');
});
test('should work correctly with `this` references', 2, function() {
var compiled = _.template('a<%= this.String("b") %>c');
- strictEqual(compiled(), 'abc');
+ equal(compiled(), 'abc');
var object = { 'b': 'B' };
object.compiled = _.template('A<%= this.b %>C', null, { 'variable': 'obj' });
- strictEqual(object.compiled(), 'ABC');
+ equal(object.compiled(), 'ABC');
});
test('should work with backslashes', 1, function() {
var compiled = _.template('<%= a %> \\b');
- strictEqual(compiled({ 'a': 'A' }), 'A \\b');
+ equal(compiled({ 'a': 'A' }), 'A \\b');
});
test('should work with escaped characters in string literals', 2, function() {
var compiled = _.template('<% print("\'\\n\\r\\t\\u2028\\u2029\\\\") %>');
- strictEqual(compiled(), "'\n\r\t\u2028\u2029\\");
+ equal(compiled(), "'\n\r\t\u2028\u2029\\");
compiled = _.template('\'\n\r\t<%= a %>\u2028\u2029\\"');
- strictEqual(compiled({ 'a': 'A' }), '\'\n\r\tA\u2028\u2029\\"');
+ equal(compiled({ 'a': 'A' }), '\'\n\r\tA\u2028\u2029\\"');
});
test('should handle \\u2028 & \\u2029 characters', 1, function() {
@@ -8775,7 +7759,7 @@
} %>"
);
- strictEqual(compiled({ 'a': 'A' }), "'a',\"A\"");
+ equal(compiled({ 'a': 'A' }), "'a',\"A\"");
});
test('should work with templates containing newlines and comments', 1, function() {
@@ -8785,7 +7769,7 @@
%><%= value %>
'
);
- strictEqual(compiled({ 'value': 3 }), '6
');
+ equal(compiled({ 'value': 3 }), '6
');
});
test('should not error with IE conditional comments enabled (test with development build)', 1, function() {
@@ -8805,7 +7789,7 @@
var compiled = _.template(''),
data = { 'type': 1 };
- strictEqual(compiled(data), '');
+ equal(compiled(data), '');
});
test('should evaluate delimiters once', 1, function() {
@@ -8818,10 +7802,10 @@
test('should match delimiters before escaping text', 1, function() {
var compiled = _.template('<<\n a \n>>', null, { 'evaluate': /<<(.*?)>>/g });
- strictEqual(compiled(), '<<\n a \n>>');
+ equal(compiled(), '<<\n a \n>>');
});
- test('should resolve `null` and `undefined` values to an empty string', 4, function() {
+ test('should resolve `null` and `undefined` values to empty strings', 4, function() {
var compiled = _.template('<%= a %><%- a %>');
strictEqual(compiled({ 'a': null }), '');
strictEqual(compiled({ 'a': undefined }), '');
@@ -8836,14 +7820,14 @@
compiled = _.template(expected, null, { 'evaluate': /<<(.+?)>>/g }),
data = { 'value': true };
- strictEqual(compiled(data), expected);
+ equal(compiled(data), expected);
});
test('should support recursive calls', 1, function() {
var compiled = _.template('<%= a %><% a = _.template(c, obj) %><%= a %>'),
data = { 'a': 'A', 'b': 'B', 'c': '<%= b %>' };
- strictEqual(compiled(data), 'AB');
+ equal(compiled(data), 'AB');
});
test('should coerce `text` argument to a string', 1, function() {
@@ -8860,10 +7844,10 @@
});
test('should not modify `_.templateSettings` when `options` are provided', 2, function() {
- ok(!('a' in _.templateSettings));
+ equal('a' in _.templateSettings, false);
_.template('', {}, { 'a': 1 });
- ok(!('a' in _.templateSettings));
+ equal('a' in _.templateSettings, false);
delete _.templateSettings.a;
});
@@ -8900,60 +7884,6 @@
/*--------------------------------------------------------------------------*/
- QUnit.module('lodash.truncate');
-
- (function() {
- var string = 'hi-diddly-ho there, neighborino';
-
- test('should truncate to a length of `30` by default', 1, function() {
- strictEqual(_.truncate(string), 'hi-diddly-ho there, neighbo...');
- });
-
- test('should not truncate if `string` is <= `length`', 2, function() {
- strictEqual(_.truncate(string, string.length), string);
- strictEqual(_.truncate(string, string.length + 2), string);
- });
-
- test('should truncate string the given length', 1, function() {
- strictEqual(_.truncate(string, 24), 'hi-diddly-ho there, n...');
- });
-
- test('should support a `omission` option', 1, function() {
- strictEqual(_.truncate(string, { 'omission': ' [...]' }), 'hi-diddly-ho there, neig [...]');
- });
-
- test('should support a `length` option', 1, function() {
- strictEqual(_.truncate(string, { 'length': 4 }), 'h...');
- });
-
- test('should support a `separator` option', 2, function() {
- strictEqual(_.truncate(string, { 'length': 24, 'separator': ' ' }), 'hi-diddly-ho there,...');
- strictEqual(_.truncate(string, { 'length': 24, 'separator': /,? +/ }), 'hi-diddly-ho there...');
- });
-
- test('should treat negative `length` as `0`', 4, function() {
- _.each([0, -2], function(length) {
- strictEqual(_.truncate(string, length), '...');
- strictEqual(_.truncate(string, { 'length': length }), '...');
- });
- });
-
- test('should coerce `length` to a number', 4, function() {
- _.each(['', '4'], function(length, index) {
- var actual = index ? 'h...' : '...';
- strictEqual(_.truncate(string, length), actual);
- strictEqual(_.truncate(string, { 'length': { 'valueOf': _.constant(length) } }), actual);
- });
- });
-
- test('should coerce `string` to a string', 2, function() {
- strictEqual(_.truncate(Object(string), 4), 'h...');
- strictEqual(_.truncate({ 'toString': _.constant(string) }, 5), 'hi...');
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
QUnit.module('lodash.throttle');
(function() {
@@ -8982,7 +7912,7 @@
asyncTest('subsequent calls should return the result of the first call', 5, function() {
if (!(isRhino && isModularize)) {
- var throttled = _.throttle(_.identity, 32),
+ var throttled = _.throttle(function(value) { return value; }, 32),
result = [throttled('a'), throttled('b')];
deepEqual(result, ['a', 'a']);
@@ -9027,7 +7957,7 @@
throttled();
setTimeout(function() {
- strictEqual(callCount, 2);
+ equal(callCount, 2);
QUnit.start();
}, 64);
}
@@ -9053,7 +7983,7 @@
}, 32);
throttled.call(object, 'a');
- strictEqual(count, 1);
+ equal(count, 1);
setTimeout(function() {
ok(count < 3);
@@ -9073,10 +8003,10 @@
throttled = _.throttle(function() { count++; }, 32);
throttled();
- strictEqual(count, 1);
+ equal(count, 1);
setTimeout(function() {
- strictEqual(count, 1);
+ equal(count, 1);
QUnit.start();
}, 64);
}
@@ -9118,8 +8048,8 @@
return value;
}, 32, {});
- strictEqual(throttled('a'), 'a');
- strictEqual(throttled('b'), 'a');
+ equal(throttled('a'), 'a');
+ equal(throttled('b'), 'a');
setTimeout(function() {
strictEqual(count, 2);
@@ -9132,14 +8062,14 @@
}
});
- test('should support a `leading` option', 4, function() {
+ test('should work with `leading` option', 4, function() {
if (!(isRhino && isModularize)) {
- _.each([true, { 'leading': true }], function(options) {
+ _.forEach([true, { 'leading': true }], function(options) {
var withLeading = _.throttle(_.identity, 32, options);
- strictEqual(withLeading('a'), 'a');
+ equal(withLeading('a'), 'a');
});
- _.each([false, { 'leading': false }], function(options) {
+ _.forEach([false, { 'leading': false }], function(options) {
var withoutLeading = _.throttle(_.identity, 32, options);
strictEqual(withoutLeading('a'), undefined);
});
@@ -9149,7 +8079,7 @@
}
});
- asyncTest('should support a `trailing` option', 6, function() {
+ asyncTest('should work with `trailing` option', 6, function() {
if (!(isRhino && isModularize)) {
var withCount = 0,
withoutCount = 0;
@@ -9164,14 +8094,14 @@
return value;
}, 64, { 'trailing': false });
- strictEqual(withTrailing('a'), 'a');
- strictEqual(withTrailing('b'), 'a');
+ equal(withTrailing('a'), 'a');
+ equal(withTrailing('b'), 'a');
- strictEqual(withoutTrailing('a'), 'a');
- strictEqual(withoutTrailing('b'), 'a');
+ equal(withoutTrailing('a'), 'a');
+ equal(withoutTrailing('b'), 'a');
setTimeout(function() {
- strictEqual(withCount, 2);
+ equal(withCount, 2);
strictEqual(withoutCount, 1);
QUnit.start();
}, 256);
@@ -9214,15 +8144,14 @@
QUnit.module('lodash.debounce and lodash.throttle');
- _.each(['debounce', 'throttle'], function(methodName) {
- var func = _[methodName],
- isThrottle = methodName == 'throttle';
+ _.forEach(['debounce', 'throttle'], function(methodName) {
+ var func = _[methodName];
test('_.' + methodName + ' should not error for non-object `options` values', 1, function() {
var pass = true;
try {
- func(_.noop, 32, 1);
+ func(noop, 32, 1);
} catch(e) {
pass = false;
}
@@ -9238,11 +8167,11 @@
};
object.funced();
- if (isThrottle) {
+ if (methodName == 'throttle') {
object.funced();
}
setTimeout(function() {
- deepEqual(actual, isThrottle ? [object, object] : [object]);
+ deepEqual(actual, methodName == 'throttle' ? [object, object] : [object]);
QUnit.start();
}, 64);
}
@@ -9275,7 +8204,7 @@
setTimeout(function() {
funced();
- strictEqual(callCount, isThrottle ? 2 : 1);
+ equal(callCount, methodName == 'throttle' ? 2 : 1);
QUnit.start();
}, 64);
}
@@ -9308,7 +8237,7 @@
QUnit.module('lodash.slice and lodash.toArray');
- _.each(['slice', 'toArray'], function(methodName) {
+ _.forEach(['slice', 'toArray'], function(methodName) {
var args = (function() { return arguments; }(1, 2, 3)),
array = [1, 2, 3],
func = _[methodName];
@@ -9319,8 +8248,8 @@
var actual = func(sparse);
- ok('0' in actual);
- ok('2' in actual);
+ ok(0 in actual);
+ ok(2 in actual);
deepEqual(actual, sparse);
});
@@ -9354,17 +8283,6 @@
QUnit.module('lodash.times');
(function() {
- test('should rollover large `n` values', 1, function() {
- var actual = _.times(Math.pow(2, 32) + 1);
- deepEqual(actual, [0]);
- });
-
- test('should coerce non-finite `n` values to `0`', 3, function() {
- _.each([-Infinity, NaN, Infinity], function(n) {
- deepEqual(_.times(n), []);
- });
- });
-
test('should pass the correct `callback` arguments', 1, function() {
var args;
@@ -9396,7 +8314,7 @@
test('should return an empty array for falsey and negative `n` arguments', 1, function() {
var values = falsey.concat(-1, -Infinity),
- expected = _.map(values, _.constant([]));
+ expected = _.map(values, function() { return []; });
var actual = _.map(values, function(value, index) {
return index ? _.times(value) : _.times();
@@ -9450,11 +8368,7 @@
ok(_.transform(new Foo) instanceof Foo);
});
- test('should check that `object` is an object before using it as the `accumulator` `[[Prototype]]', 1, function() {
- ok(!(_.transform(1) instanceof Number));
- });
-
- _.each({
+ _.forEach({
'array': [1, 2, 3],
'object': { 'a': 1, 'b': 2, 'c': 3 }
},
@@ -9468,10 +8382,10 @@
var first = args[0];
if (key == 'array') {
- ok(first !== object && _.isArray(first));
+ ok(first != object && _.isArray(first));
deepEqual(args, [first, 1, 0, object]);
} else {
- ok(first !== object && _.isPlainObject(first));
+ ok(first != object && _.isPlainObject(first));
deepEqual(args, [first, 1, 'a', object]);
}
});
@@ -9491,7 +8405,7 @@
QUnit.module('trim methods');
- _.each(['trim', 'trimLeft', 'trimRight'], function(methodName, index) {
+ _.forEach(['trim', 'trimLeft', 'trimRight'], function(methodName, index) {
var func = _[methodName];
var parts = [];
@@ -9508,13 +8422,6 @@
strictEqual(func(string), (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : ''));
});
- test('`_.' + methodName + '` should not remove non-whitespace characters', 1, function() {
- var problemChars = '\x85\u200b\ufffe',
- string = problemChars + 'a b c' + problemChars;
-
- strictEqual(func(string), string);
- });
-
test('`_.' + methodName + '` should coerce `string` to a string', 1, function() {
var object = { 'toString': function() { return whitespace + 'a b c' + whitespace; } };
strictEqual(func(object), (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : ''));
@@ -9532,22 +8439,13 @@
strictEqual(func(string, object), (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : ''));
});
- test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string and `chars`', 6, function() {
- _.each([null, '_-'], function(chars) {
- strictEqual(func(null, chars), '');
- strictEqual(func(undefined, chars), '');
- strictEqual(func('', chars), '');
+ test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty strings', 6, function() {
+ _.forEach([null, '_-'], function(arg) {
+ strictEqual(func.call(_, null, arg), '');
+ strictEqual(func.call(_, undefined, arg), '');
+ strictEqual(func.call(_, '', arg), '');
});
});
-
- test('`_.' + methodName + '` should work with `null`, `undefined`, or empty string for `chars`', 3, function() {
- var string = whitespace + 'a b c' + whitespace,
- expected = (index == 2 ? whitespace : '') + 'a b c' + (index == 1 ? whitespace : '');
-
- strictEqual(func(string, null), expected);
- strictEqual(func(string, undefined), expected);
- strictEqual(func(string, ''), string);
- });
});
/*--------------------------------------------------------------------------*/
@@ -9559,23 +8457,29 @@
unescaped = '&<>"\'\/';
test('should unescape entities in the correct order', 1, function() {
- strictEqual(_.unescape('<'), '<');
+ equal(_.unescape('<'), '<');
});
test('should unescape the proper entities', 1, function() {
- strictEqual(_.unescape(escaped), unescaped);
+ equal(_.unescape(escaped), unescaped);
});
test('should not unescape the "/" entity', 1, function() {
- strictEqual(_.unescape('/'), '/');
+ equal(_.unescape('/'), '/');
});
test('should handle strings with nothing to unescape', 1, function() {
- strictEqual(_.unescape('abc'), 'abc');
+ equal(_.unescape('abc'), 'abc');
});
test('should unescape the same characters escaped by `_.escape`', 1, function() {
- strictEqual(_.unescape(_.escape(unescaped)), unescaped);
+ equal(_.unescape(_.escape(unescaped)), unescaped);
+ });
+
+ test('should return an empty string when provided `null`, `undefined`, or empty strings', 3, function() {
+ strictEqual(_.unescape(null), '');
+ strictEqual(_.unescape(undefined), '');
+ strictEqual(_.unescape(''), '');
});
}());
@@ -9584,25 +8488,28 @@
QUnit.module('lodash.union');
(function() {
- var args = arguments;
-
test('should return the union of the given arrays', 1, function() {
- var actual = _.union([1, 3, 2], [5, 2, 1, 4], [2, 1]);
- deepEqual(actual, [1, 3, 2, 5, 4]);
+ var actual = _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+ deepEqual(actual, [1, 2, 3, 5, 4]);
});
test('should not flatten nested arrays', 1, function() {
- var actual = _.union([1, 3, 2], [1, [5]], [2, [4]]);
- deepEqual(actual, [1, 3, 2, [5], [4]]);
+ var actual = _.union([1, 2, 3], [1, [5]], [2, [4]]);
+ deepEqual(actual, [1, 2, 3, [5], [4]]);
});
- test('should ignore values that are not arrays or `arguments` objects', 3, function() {
- var array = [0];
- deepEqual(_.union(array, 3, null, { '0': 1 }), array);
- deepEqual(_.union(null, array, null, [2, 1]), [0, 2, 1]);
- deepEqual(_.union(null, array, null, args), [0, 1, 2, 3]);
+ test('should produce correct results when provided a falsey `array` argument', 1, function() {
+ var expected = [1, 2, 3],
+ actual = _.union(null, expected);
+
+ deepEqual(actual, expected);
});
- }(1, 2, 3));
+
+ test('should ignore individual secondary values', 1, function() {
+ var array = [1];
+ deepEqual(_.union(array, 1, 2, 3), array);
+ });
+ }());
/*--------------------------------------------------------------------------*/
@@ -9660,7 +8567,7 @@
test('should work with large arrays', 1, function() {
var object = {};
- var largeArray = _.times(largeArraySize, function(index) {
+ var largeArray = _.times(LARGE_ARRAY_SIZE, function(index) {
switch (index % 3) {
case 0: return 0;
case 1: return 'a';
@@ -9674,19 +8581,18 @@
test('should work with large arrays of boolean, `null`, and `undefined` values', 1, function() {
var array = [],
expected = [true, false, null, undefined],
- count = Math.ceil(largeArraySize / expected.length);
+ count = Math.ceil(LARGE_ARRAY_SIZE / expected.length);
_.times(count, function() {
push.apply(array, expected);
});
-
deepEqual(_.uniq(array), expected);
});
test('should distinguish between numbers and numeric strings', 1, function() {
var array = [],
expected = ['2', 2, Object('2'), Object(2)],
- count = Math.ceil(largeArraySize / expected.length);
+ count = Math.ceil(LARGE_ARRAY_SIZE / expected.length);
_.times(count, function() {
push.apply(array, expected);
@@ -9695,7 +8601,7 @@
deepEqual(_.uniq(array), expected);
});
- _.each({
+ _.forEach({
'an object': ['a'],
'a number': 0,
'a string': '0'
@@ -9723,11 +8629,11 @@
actual.push(_.uniqueId());
});
- strictEqual(_.uniq(actual).length, actual.length);
+ equal(_.uniq(actual).length, actual.length);
});
test('should return a string value when not passing a prefix argument', 1, function() {
- strictEqual(typeof _.uniqueId(), 'string');
+ equal(typeof _.uniqueId(), 'string');
});
test('should coerce the prefix argument to a string', 1, function() {
@@ -9757,7 +8663,7 @@
QUnit.module('lodash.where');
(function() {
- var objects = [
+ var array = [
{ 'a': 1 },
{ 'a': 1 },
{ 'a': 1, 'b': 2 },
@@ -9765,27 +8671,22 @@
{ 'a': 3 }
];
- test('should filter by `source` properties', 6, function() {
- deepEqual(_.where(objects, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]);
- deepEqual(_.where(objects, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]);
- deepEqual(_.where(objects, { 'a': 3 }), [{ 'a': 3 }]);
- deepEqual(_.where(objects, { 'b': 1 }), []);
- deepEqual(_.where(objects, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]);
- deepEqual(_.where(objects, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]);
+ test('should filter by properties', 6, function() {
+ deepEqual(_.where(array, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]);
+ deepEqual(_.where(array, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]);
+ deepEqual(_.where(array, { 'a': 3 }), [{ 'a': 3 }]);
+ deepEqual(_.where(array, { 'b': 1 }), []);
+ deepEqual(_.where(array, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]);
+ deepEqual(_.where(array, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]);
});
- test('should not filter by inherited `source` properties', 2, function() {
+ test('should not filter by inherited properties', 1, function() {
function Foo() {}
Foo.prototype = { 'a': 2 };
- var source = new Foo;
- source.b = 2;
-
- var expected = [objects[2], objects[3]],
- actual = _.where(objects, source);
-
- deepEqual(actual, expected);
- ok(_.isEmpty(_.difference(actual, objects)));
+ var properties = new Foo;
+ properties.b = 2;
+ deepEqual(_.where(array, properties), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]);
});
test('should filter by problem JScript properties (test in IE < 9)', 1, function() {
@@ -9793,83 +8694,47 @@
deepEqual(_.where(collection, shadowedObject), [shadowedObject]);
});
- test('should work with an object for `collection`', 2, function() {
+ test('should work with an object for `collection`', 1, function() {
var collection = {
'x': { 'a': 1 },
'y': { 'a': 3 },
'z': { 'a': 1, 'b': 2 }
};
- var expected = [collection.x, collection.z],
- actual = _.where(collection, { 'a': 1 });
-
- deepEqual(actual, expected);
- ok(_.isEmpty(_.difference(actual, _.values(collection))));
+ deepEqual(_.where(collection, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1, 'b': 2 }]);
});
- test('should work with a function for `source`', 1, function() {
- function source() {}
- source.a = 2;
-
- deepEqual(_.where(objects, source), [{ 'a': 2, 'b': 2 }]);
+ test('should return an empty array when provided an empty `properties` object', 1, function() {
+ deepEqual(_.where(array, {}), []);
});
- test('should match all elements when provided an empty `source`', 1, function() {
- var expected = _.map(empties, _.constant(objects));
-
- var actual = _.map(empties, function(value) {
- var result = _.where(objects, value);
- return result !== objects && result;
- });
-
- deepEqual(actual, expected);
- });
-
- test('should perform a deep partial comparison of `source`', 2, function() {
+ test('should deep compare `properties` values', 1, function() {
var collection = [{ 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4 }],
- expected = collection.slice(),
- actual = _.where(collection, { 'a': { 'b': { 'c': 1 } } });
+ expected = _.cloneDeep(collection);
- deepEqual(actual, expected);
- ok(_.isEmpty(_.difference(actual, collection)));
+ deepEqual(_.where(collection, { 'a': { 'b': { 'c': 1 } } }), expected);
});
test('should search of arrays for values', 2, function() {
var collection = [{ 'a': [1, 2] }],
- expected = collection.slice();
+ expected = _.cloneDeep(collection);
deepEqual(_.where(collection, { 'a': [] }), []);
deepEqual(_.where(collection, { 'a': [2] }), expected);
});
- test('should perform a partial comparison of *all* objects within arrays of `source`', 2, function() {
- var collection = [
- { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 5, 'd': 6 }] },
- { 'a': [{ 'b': 1, 'c': 2, 'd': 3 }, { 'b': 4, 'c': 6, 'd': 7 }] }
- ];
-
- var actual = _.where(collection, { 'a': [{ 'b': 1, 'c': 2 }, { 'b': 4, 'c': 5 }] });
- deepEqual(actual, [collection[0]]);
- ok(_.isEmpty(_.difference(actual, collection)));
- });
-
- test('should handle a `source` with `undefined` values', 4, function() {
- var source = { 'b': undefined },
- actual = _.where([{ 'a': 1 }, { 'a': 1, 'b': 1 }], source);
-
- deepEqual(actual, []);
+ test('should handle `properties` with `undefined` values', 4, function() {
+ var properties = { 'b': undefined };
+ deepEqual(_.where([{ 'a': 1 }, { 'a': 1, 'b': 1 }], properties), []);
var object = { 'a': 1, 'b': undefined };
- actual = _.where([object], source);
- deepEqual(actual, [object]);
+ deepEqual(_.where([object], properties), [object]);
- source = { 'a': { 'c': undefined } };
- actual = _.where([{ 'a': { 'b': 1 } }, { 'a':{ 'b':1 , 'c': 1 } }], source);
- deepEqual(actual, []);
+ properties = { 'a': { 'c': undefined } };
+ deepEqual(_.where([{ 'a': { 'b': 1 } }, { 'a':{ 'b':1 , 'c': 1 } }], properties), []);
object = { 'a': { 'b': 1, 'c': undefined } };
- actual = _.where([object], source);
- deepEqual(actual, [object]);
+ deepEqual(_.where([object], properties), [object]);
});
}());
@@ -9903,18 +8768,18 @@
return '' + func(text) + '
';
});
- strictEqual(p('fred, barney, & pebbles'), 'fred, barney, & pebbles
');
+ equal(p('fred, barney, & pebbles'), 'fred, barney, & pebbles
');
});
test('should pass the correct `wrapper` arguments', 1, function() {
var args;
- var wrapped = _.wrap(_.noop, function() {
+ var wrapped = _.wrap(noop, function() {
args || (args = slice.call(arguments));
});
wrapped(1, 2, 3);
- deepEqual(args, [_.noop, 1, 2, 3]);
+ deepEqual(args, [noop, 1, 2, 3]);
});
test('should not set a `this` binding', 1, function() {
@@ -9923,7 +8788,7 @@
});
var object = { 'p': p, 'text': 'fred, barney, & pebbles' };
- strictEqual(object.p(), 'fred, barney, & pebbles
');
+ equal(object.p(), 'fred, barney, & pebbles
');
});
}());
@@ -9932,8 +8797,6 @@
QUnit.module('lodash.xor');
(function() {
- var args = arguments;
-
test('should return the symmetric difference of the given arrays', 1, function() {
var actual = _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
deepEqual(actual, [1, 4, 5]);
@@ -9963,18 +8826,11 @@
}
});
- test('should ignore individual secondary arguments', 1, function() {
- var array = [0];
- deepEqual(_.xor(array, 3, null, { '0': 1 }), array);
+ test('should ignore individual secondary values', 1, function() {
+ var array = [1, null, 3];
+ deepEqual(_.xor(array, 3, null), array);
});
-
- test('should ignore values that are not arrays or `arguments` objects', 3, function() {
- var array = [1, 2];
- deepEqual(_.xor(array, 3, null, { '0': 1 }), array);
- deepEqual(_.xor(null, array, null, [2, 3]), [1, 3]);
- deepEqual(_.xor(null, array, null, args), [3]);
- });
- }(1, 2, 3));
+ }());
/*--------------------------------------------------------------------------*/
@@ -10015,11 +8871,11 @@
];
var actual = _.zip(pair[0]);
- ok('0' in actual[2]);
+ ok(0 in actual[2]);
deepEqual(actual, pair[1]);
actual = _.zip.apply(_, actual);
- ok('2' in actual[0]);
+ ok(2 in actual[0]);
deepEqual(actual, [['barney', 36, undefined], ['fred', 40, false]]);
});
@@ -10066,7 +8922,7 @@
});
test('should accept a falsey `array` argument', 1, function() {
- var expected = _.map(falsey, _.constant({}));
+ var expected = _.map(falsey, function() { return {}; });
var actual = _.map(falsey, function(value, index) {
try {
@@ -10097,7 +8953,7 @@
wrapped.shift();
deepEqual(wrapped.keys().value(), ['length']);
- strictEqual(wrapped.first(), undefined);
+ equal(wrapped.first(), undefined);
}
else {
skipTest(2);
@@ -10116,7 +8972,7 @@
wrapped.splice(0, 1);
deepEqual(wrapped.keys().value(), ['length']);
- strictEqual(wrapped.first(), undefined);
+ equal(wrapped.first(), undefined);
}
else {
skipTest(2);
@@ -10132,7 +8988,7 @@
test('should return the `toString` result of the wrapped value', 1, function() {
if (!isNpm) {
var wrapped = _([1, 2, 3]);
- strictEqual(String(wrapped), '1,2,3');
+ equal(String(wrapped), '1,2,3');
}
else {
skipTest();
@@ -10148,33 +9004,12 @@
test('should return the `valueOf` result of the wrapped value', 1, function() {
if (!isNpm) {
var wrapped = _(123);
- strictEqual(Number(wrapped), 123);
+ equal(Number(wrapped), 123);
}
else {
skipTest();
}
});
-
- test('should stringify the wrapped value when passed to `JSON.stringify`', 1, function() {
- if (!isNpm && JSON) {
- var wrapped = _([1, 2, 3]);
- strictEqual(JSON.stringify(wrapped), '[1,2,3]');
- }
- else {
- skipTest();
- }
- });
-
- test('should be aliased', 2, function() {
- if (!isNpm) {
- var expected = _.prototype.valueOf;
- strictEqual(_.prototype.toJSON, expected);
- strictEqual(_.prototype.value, expected);
- }
- else {
- skipTest(2);
- }
- });
}());
/*--------------------------------------------------------------------------*/
@@ -10192,7 +9027,7 @@
'unshift'
];
- _.each(funcs, function(methodName) {
+ _.forEach(funcs, function(methodName) {
test('`_(...).' + methodName + '` should return the existing wrapped value', 1, function() {
if (!isNpm) {
strictEqual(wrapped[methodName](), wrapped);
@@ -10218,7 +9053,7 @@
'splice'
];
- _.each(funcs, function(methodName) {
+ _.forEach(funcs, function(methodName) {
test('`_(...).' + methodName + '` should return a new wrapped value', 1, function() {
if (!isNpm) {
ok(wrapped[methodName]() instanceof _);
@@ -10271,14 +9106,14 @@
'some'
];
- _.each(funcs, function(methodName) {
+ _.forEach(funcs, function(methodName) {
test('`_(...).' + methodName + '` should return an unwrapped value', 1, function() {
if (!isNpm) {
var actual = methodName == 'reduceRight'
? wrapped[methodName](_.identity)
: wrapped[methodName]();
- ok(!(actual instanceof _));
+ equal(actual instanceof _, false);
}
else {
skipTest();
@@ -10301,10 +9136,10 @@
'sample'
];
- _.each(funcs, function(methodName) {
+ _.forEach(funcs, function(methodName) {
test('`_(...).' + methodName + '` called without an `n` argument should return an unwrapped value', 1, function() {
if (!isNpm) {
- strictEqual(typeof wrapped[methodName](), 'number');
+ equal(typeof wrapped[methodName](), 'number');
}
else {
skipTest();
@@ -10323,10 +9158,10 @@
test('`_.' + methodName + '` should return `undefined` when querying falsey arguments without an `n` argument', 1, function() {
if (!isNpm) {
var actual = [],
- expected = _.map(falsey, _.constant()),
+ expected = _.map(falsey, function() { return undefined; }),
func = _[methodName];
- _.each(falsey, function(value, index) {
+ _.forEach(falsey, function(value, index) {
try {
actual.push(index ? func(value) : func());
} catch(e) { }
@@ -10341,7 +9176,7 @@
test('`_.' + methodName + '` should return an empty array when querying falsey arguments with an `n` argument', 1, function() {
if (!isNpm) {
- var expected = _.map(falsey, _.constant([])),
+ var expected = _.map(falsey, function() { return []; }),
func = _[methodName];
var actual = _.map(falsey, function(value, index) {
@@ -10402,22 +9237,21 @@
deepEqual([args[0], args[1], args[2]], [1, [3], 5], message('pull'));
_.remove(args, function(value) { return typeof value == 'number'; });
- ok(args.length === 1 && _.isEqual(args[0], [3]), message('remove'));
+ ok(args.length == 1 && _.isEqual(args[0], [3]), message('remove'));
}
else {
skipTest(2)
}
});
- test('should accept falsey primary arguments', 4, function() {
+ test('should accept falsey primary arguments', 3, function() {
function message(methodName) {
return '`_.' + methodName + '` should accept falsey primary arguments';
}
- deepEqual(_.difference(null, array), array, message('difference'));
- deepEqual(_.intersection(null, array), array, message('intersection'));
+ deepEqual(_.difference(null, array), [], message('difference'));
+ deepEqual(_.intersection(null, array), [], message('intersection'));
deepEqual(_.union(null, array), array, message('union'));
- deepEqual(_.xor(null, array), array, message('xor'));
});
test('should accept falsey secondary arguments', 3, function() {
@@ -10426,49 +9260,13 @@
}
deepEqual(_.difference(array, null), array, message('difference'));
- deepEqual(_.intersection(array, null), array, message('intersection'));
+ deepEqual(_.intersection(array, null), [], message('intersection'));
deepEqual(_.union(array, null), array, message('union'));
});
}(1, null, [3], null, 5));
/*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
-
- QUnit.module('"Strings" category methods');
-
- (function() {
- var stringMethods = [
- 'camelCase',
- 'capitalize',
- 'escape',
- 'escapeRegExp',
- 'kebabCase',
- 'pad',
- 'padLeft',
- 'padRight',
- 'repeat',
- 'snakeCase',
- 'trim',
- 'trimLeft',
- 'trimRight',
- 'truncate',
- 'unescape'
- ];
-
- _.each(stringMethods, function(methodName) {
- var func = _[methodName];
-
- test('`_.' + methodName + '` should return an empty string when provided `null`, `undefined`, or empty string', 3, function() {
- strictEqual(func(null), '');
- strictEqual(func(undefined), '');
- strictEqual(func(''), '');
- });
- });
- }());
-
- /*--------------------------------------------------------------------------*/
-
QUnit.module('lodash methods');
(function() {
@@ -10496,6 +9294,7 @@
'range',
'reject',
'remove',
+ 'removeAt',
'rest',
'sample',
'shuffle',
@@ -10520,7 +9319,6 @@
'defer',
'delay',
'memoize',
- 'negate',
'once',
'partial',
'partialRight',
@@ -10531,12 +9329,12 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey);
- test('should accept falsey arguments', 185, function() {
- var emptyArrays = _.map(falsey, _.constant([])),
+ test('should accept falsey arguments', 167, function() {
+ var emptyArrays = _.map(falsey, function() { return []; }),
isExposed = '_' in root,
oldDash = root._;
- _.each(acceptFalsey, function(methodName) {
+ _.forEach(acceptFalsey, function(methodName) {
var expected = emptyArrays,
func = _[methodName],
pass = true;
@@ -10567,17 +9365,17 @@
});
// skip tests for missing methods of modularized builds
- _.each(['noConflict', 'runInContext', 'tap'], function(methodName) {
+ _.forEach(['noConflict', 'runInContext', 'tap'], function(methodName) {
if (!_[methodName]) {
skipTest();
}
});
});
- test('should return an array', 64, function() {
+ test('should return an array', 66, function() {
var array = [1, 2, 3];
- _.each(returnArrays, function(methodName) {
+ _.forEach(returnArrays, function(methodName) {
var actual,
func = _[methodName];
@@ -10596,13 +9394,13 @@
ok(_.isArray(actual), '_.' + methodName + ' returns an array');
var isPull = methodName == 'pull';
- strictEqual(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array');
+ equal(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array');
});
});
- test('should throw a TypeError for falsey arguments', 15, function() {
- _.each(rejectFalsey, function(methodName) {
- var expected = _.map(falsey, _.constant(true)),
+ test('should reject falsey arguments', 14, function() {
+ _.forEach(rejectFalsey, function(methodName) {
+ var expected = _.map(falsey, function() { return true; }),
func = _[methodName];
var actual = _.map(falsey, function(value, index) {
@@ -10619,18 +9417,14 @@
});
});
- test('should handle `null` `thisArg` arguments', 44, function() {
- var expected = (function() { return this; }).call(null);
+ test('should handle `null` `thisArg` arguments', 30, function() {
+ var thisArg,
+ callback = function() { thisArg = this; },
+ expected = (function() { return this; }).call(null);
var funcs = [
- 'assign',
- 'clone',
- 'cloneDeep',
'countBy',
- 'dropWhile',
- 'dropRightWhile',
'every',
- 'flatten',
'filter',
'find',
'findIndex',
@@ -10645,14 +9439,10 @@
'forOwn',
'forOwnRight',
'groupBy',
- 'isEqual',
'map',
- 'mapValues',
'max',
- 'merge',
'min',
'omit',
- 'partition',
'pick',
'reduce',
'reduceRight',
@@ -10661,46 +9451,38 @@
'some',
'sortBy',
'sortedIndex',
- 'takeWhile',
- 'takeRightWhile',
- 'tap',
'times',
- 'transform',
'uniq'
];
- _.each(funcs, function(methodName) {
- var actual,
- array = ['a'],
+ _.forEach(funcs, function(methodName) {
+ var array = ['a'],
func = _[methodName],
message = '`_.' + methodName + '` handles `null` `thisArg` arguments';
- function callback() {
- actual = this;
+ thisArg = undefined;
+
+ if (/^reduce/.test(methodName)) {
+ func(array, callback, 0, null);
+ } else if (methodName == 'sortedIndex') {
+ func(array, 'a', callback, null);
+ } else if (methodName == 'times') {
+ func(1, callback, null);
+ } else {
+ func(array, callback, null);
}
- if (func) {
- if (/^reduce/.test(methodName) || methodName == 'transform') {
- func(array, callback, 0, null);
- } else if (_.contains(['assign', 'merge'], methodName)) {
- func(array, array, callback, null);
- } else if (_.contains(['isEqual', 'sortedIndex'], methodName)) {
- func(array, 'a', callback, null);
- } else if (methodName == 'times') {
- func(1, callback, null);
- } else {
- func(array, callback, null);
- }
- strictEqual(actual, expected, message);
- }
- else {
- skipTest();
+
+ if (expected === null) {
+ strictEqual(thisArg, null, message);
+ } else {
+ equal(thisArg, expected, message);
}
});
});
test('should not contain minified method names (test production builds)', 1, function() {
ok(_.every(_.functions(_), function(methodName) {
- return methodName.length > 2 || methodName === 'at';
+ return methodName.length > 2 || methodName == 'at';
}));
});
}());