mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 10:57:49 +00:00
_.isEqual: Ensure commutative equality for dates and RegExps.
This commit is contained in:
@@ -79,9 +79,13 @@ $(document).ready(function() {
|
|||||||
ok(NaN != NaN, 'NaN is not equal to NaN (native equality)');
|
ok(NaN != NaN, 'NaN is not equal to NaN (native equality)');
|
||||||
ok(NaN !== NaN, 'NaN is not equal to NaN (native identity)');
|
ok(NaN !== NaN, 'NaN is not equal to NaN (native identity)');
|
||||||
ok(_.isEqual(NaN, NaN), 'NaN is equal to NaN');
|
ok(_.isEqual(NaN, NaN), 'NaN is equal to NaN');
|
||||||
|
ok(!_.isEqual(5, NaN), '`5` is not equal to `NaN`');
|
||||||
|
ok(!_.isEqual(false, NaN), '`false` is not equal to `NaN`');
|
||||||
ok(_.isEqual(new Date(100), new Date(100)), 'identical dates are equal');
|
ok(_.isEqual(new Date(100), new Date(100)), 'identical dates are equal');
|
||||||
ok(_.isEqual((/hello/ig), (/hello/ig)), 'identical regexes are equal');
|
ok(_.isEqual((/hello/ig), (/hello/ig)), 'identical regexes are equal');
|
||||||
|
ok(!_.isEqual({source: '(?:)', global: true, multiline: true, ignoreCase: true}, /(?:)/gim), 'RegExp-like objects and RegExps are not equal');
|
||||||
ok(!_.isEqual(null, [1]), 'a falsy is never equal to a truthy');
|
ok(!_.isEqual(null, [1]), 'a falsy is never equal to a truthy');
|
||||||
|
ok(!_.isEqual(undefined, null), '`undefined` is not equal to `null`');
|
||||||
ok(_.isEqual({isEqual: function () { return true; }}, {}), 'first object implements `isEqual`');
|
ok(_.isEqual({isEqual: function () { return true; }}, {}), 'first object implements `isEqual`');
|
||||||
ok(_.isEqual({}, {isEqual: function () { return true; }}), 'second object implements `isEqual`');
|
ok(_.isEqual({}, {isEqual: function () { return true; }}), 'second object implements `isEqual`');
|
||||||
ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), 'objects with the same number of undefined keys are not equal');
|
ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), 'objects with the same number of undefined keys are not equal');
|
||||||
|
|||||||
@@ -595,7 +595,8 @@
|
|||||||
|
|
||||||
// Internal recursive comparison function.
|
// Internal recursive comparison function.
|
||||||
function eq(a, b, stack) {
|
function eq(a, b, stack) {
|
||||||
// Identical objects are equal.
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||||||
|
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
||||||
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
||||||
// 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;
|
||||||
@@ -604,17 +605,21 @@
|
|||||||
if (typeA != typeof b) return false;
|
if (typeA != typeof b) return false;
|
||||||
// The type comparison above prevents unwanted type coercion.
|
// The type comparison above prevents unwanted type coercion.
|
||||||
if (a == b) return true;
|
if (a == b) return true;
|
||||||
// Ensure that both values are truthy or falsy.
|
// Optimization; ensure that both values are truthy or falsy.
|
||||||
if ((!a && b) || (a && !b)) return false;
|
if ((!a && b) || (a && !b)) return false;
|
||||||
// `NaN` values are equal.
|
// `NaN` values are equal.
|
||||||
if (_.isNaN(a)) return _.isNaN(b);
|
if (_.isNaN(a)) return _.isNaN(b);
|
||||||
if (_.isDate(a)) return _.isDate(b) && a.getTime() == b.getTime();
|
// Compare dates by their millisecond values.
|
||||||
|
var isDateA = _.isDate(a), isDateB = _.isDate(b);
|
||||||
|
if (isDateA || isDateB) return isDateA && isDateB && a.getTime() == b.getTime();
|
||||||
// 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 &&
|
var isRegExpA = _.isRegExp(a), isRegExpB = _.isRegExp(b);
|
||||||
a.global == b.global &&
|
if (isRegExpA || isRegExpB) return isRegExpA && isRegExpB &&
|
||||||
a.multiline == b.multiline &&
|
a.source == b.source &&
|
||||||
a.ignoreCase == b.ignoreCase;
|
a.global == b.global &&
|
||||||
// Recursively compare objects and arrays.
|
a.multiline == b.multiline &&
|
||||||
|
a.ignoreCase == b.ignoreCase;
|
||||||
|
// Ensure that both values are objects.
|
||||||
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;
|
||||||
@@ -629,9 +634,9 @@
|
|||||||
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.
|
// Add the first object to the stack of traversed objects.
|
||||||
stack.push(a);
|
stack.push(a);
|
||||||
// Deep compare the contents.
|
// Deep compare the two objects.
|
||||||
var size = 0, sizeRight = 0, result = true, key;
|
var size = 0, sizeRight = 0, result = true, key;
|
||||||
for (key in a) {
|
for (key in a) {
|
||||||
// Count the expected number of properties.
|
// Count the expected number of properties.
|
||||||
@@ -646,7 +651,7 @@
|
|||||||
}
|
}
|
||||||
result = size == sizeRight;
|
result = size == sizeRight;
|
||||||
}
|
}
|
||||||
// Remove the object from the stack of traversed objects.
|
// Remove the first object from the stack of traversed objects.
|
||||||
stack.pop();
|
stack.pop();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user