mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-06 09:47:48 +00:00
_.isEqual: Move the internal eq method into the main closure. Remove strict type checking.
This commit is contained in:
113
underscore.js
113
underscore.js
@@ -593,64 +593,63 @@
|
|||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Perform a deep comparison to check if two objects are equal.
|
// Internal recursive comparison function.
|
||||||
_.isEqual = (function() {
|
function eq(a, b, stack) {
|
||||||
function eq(a, b, stack) {
|
// Identical objects are equal.
|
||||||
// Identical objects are equal.
|
if (a === b) return true;
|
||||||
if (a === b) return true;
|
// A strict comparison is necessary because `null == undefined`.
|
||||||
// A strict comparison is necessary because `null == undefined`.
|
if (a == null) return a === b;
|
||||||
if (a == null) return a === b;
|
// Compare object types.
|
||||||
// Compare object types.
|
var typeA = typeof a;
|
||||||
var typeA = typeof a;
|
if (typeA != typeof b) return false;
|
||||||
if (typeA != typeof b) return false;
|
// The type comparison above prevents unwanted type coercion.
|
||||||
// Compare functions by reference.
|
if (a == b) return true;
|
||||||
if (_.isFunction(a)) return _.isFunction(b) && a == b;
|
// Ensure that both values are truthy or falsy.
|
||||||
// Compare strings, numbers, dates, and booleans by value.
|
if ((!a && b) || (a && !b)) return false;
|
||||||
if (_.isString(a)) return _.isString(b) && String(a) == String(b);
|
// `NaN` values are toxic.
|
||||||
if (_.isNumber(a)) return _.isNumber(b) && +a == +b;
|
if (_.isNaN(a) || _.isNaN(b)) return false;
|
||||||
if (_.isDate(a)) return _.isDate(b) && a.getTime() == b.getTime();
|
if (_.isDate(a)) return _.isDate(b) && a.getTime() == b.getTime();
|
||||||
if (_.isBoolean(a)) return _.isBoolean(b) && +a == +b;
|
// Compare RegExps by their source patterns and flags.
|
||||||
// Compare RegExps by their source patterns and flags.
|
if (_.isRegExp(a)) return _.isRegExp(b) && a.source == b.source &&
|
||||||
if (_.isRegExp(a)) return _.isRegExp(b) && a.source == b.source &&
|
a.global == b.global &&
|
||||||
a.global == b.global &&
|
a.multiline == b.multiline &&
|
||||||
a.multiline == b.multiline &&
|
a.ignoreCase == b.ignoreCase;
|
||||||
a.ignoreCase == b.ignoreCase;
|
// Recursively compare objects and arrays.
|
||||||
// Recursively compare objects and arrays.
|
if (typeA != 'object') return false;
|
||||||
if (typeA != 'object') return false;
|
// Unwrap any wrapped objects.
|
||||||
// Unwrap any wrapped objects.
|
if (a._chain) a = a._wrapped;
|
||||||
if (a._chain) a = a._wrapped;
|
if (b._chain) b = b._wrapped;
|
||||||
if (b._chain) b = b._wrapped;
|
// Invoke a custom `isEqual` method if one is provided.
|
||||||
// Invoke a custom `isEqual` method if one is provided.
|
if (a.isEqual) return a.isEqual(b);
|
||||||
if (a.isEqual) return a.isEqual(b);
|
if (b.isEqual) return b.isEqual(a);
|
||||||
if (b.isEqual) return b.isEqual(a);
|
// Compare array lengths to determine if a deep comparison is necessary.
|
||||||
// Compare array lengths to determine if a deep comparison is necessary.
|
if (a.length && (a.length !== b.length)) return false;
|
||||||
if (a.length && (a.length !== b.length)) return false;
|
// Assume equality for cyclic structures.
|
||||||
// Assume equality for cyclic structures.
|
var length = stack.length;
|
||||||
var length = stack.length;
|
while (length--) {
|
||||||
while (length--) {
|
if (stack[length] == a) return true;
|
||||||
if (stack[length] == a) return true;
|
|
||||||
}
|
|
||||||
// Add the object to the stack of traversed objects.
|
|
||||||
stack.push(a);
|
|
||||||
var result = true;
|
|
||||||
// Deep comparse the contents.
|
|
||||||
var aKeys = _.keys(a), bKeys = _.keys(b);
|
|
||||||
// Ensure that both objects contain the same number of properties.
|
|
||||||
if (result = aKeys.length == bKeys.length) {
|
|
||||||
// Recursively compare properties.
|
|
||||||
for (var key in a) {
|
|
||||||
if (!(result = key in b && eq(a[key], b[key], stack))) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Remove the object from the stack of traversed objects.
|
|
||||||
stack.pop();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
// Expose the recursive `isEqual` method.
|
// Add the object to the stack of traversed objects.
|
||||||
return function(a, b) {
|
stack.push(a);
|
||||||
return eq(a, b, []);
|
var result = true;
|
||||||
};
|
// Deep comparse the contents.
|
||||||
})();
|
var aKeys = _.keys(a), bKeys = _.keys(b);
|
||||||
|
// Ensure that both objects contain the same number of properties.
|
||||||
|
if (result = aKeys.length == bKeys.length) {
|
||||||
|
// Recursively compare properties.
|
||||||
|
for (var key in a) {
|
||||||
|
if (!(result = key in b && eq(a[key], b[key], stack))) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the object from the stack of traversed objects.
|
||||||
|
stack.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a deep comparison to check if two objects are equal.
|
||||||
|
_.isEqual = function(a, b) {
|
||||||
|
return eq(a, b, []);
|
||||||
|
};
|
||||||
|
|
||||||
// Is a given array or object empty?
|
// Is a given array or object empty?
|
||||||
_.isEmpty = function(obj) {
|
_.isEmpty = function(obj) {
|
||||||
|
|||||||
Reference in New Issue
Block a user