UNPKG

2.66 kBJavaScriptView Raw
1import baseHas from './_baseHas';
2import keys from './keys';
3
4/** Used to compose bitmasks for comparison styles. */
5var PARTIAL_COMPARE_FLAG = 2;
6
7/**
8 * A specialized version of `baseIsEqualDeep` for objects with support for
9 * partial deep comparisons.
10 *
11 * @private
12 * @param {Object} object The object to compare.
13 * @param {Object} other The other object to compare.
14 * @param {Function} equalFunc The function to determine equivalents of values.
15 * @param {Function} customizer The function to customize comparisons.
16 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
17 * for more details.
18 * @param {Object} stack Tracks traversed `object` and `other` objects.
19 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
20 */
21function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
22 var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
23 objProps = keys(object),
24 objLength = objProps.length,
25 othProps = keys(other),
26 othLength = othProps.length;
27
28 if (objLength != othLength && !isPartial) {
29 return false;
30 }
31 var index = objLength;
32 while (index--) {
33 var key = objProps[index];
34 if (!(isPartial ? key in other : baseHas(other, key))) {
35 return false;
36 }
37 }
38 // Assume cyclic values are equal.
39 var stacked = stack.get(object);
40 if (stacked) {
41 return stacked == other;
42 }
43 var result = true;
44 stack.set(object, other);
45
46 var skipCtor = isPartial;
47 while (++index < objLength) {
48 key = objProps[index];
49 var objValue = object[key],
50 othValue = other[key];
51
52 if (customizer) {
53 var compared = isPartial
54 ? customizer(othValue, objValue, key, other, object, stack)
55 : customizer(objValue, othValue, key, object, other, stack);
56 }
57 // Recursively compare objects (susceptible to call stack limits).
58 if (!(compared === undefined
59 ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
60 : compared
61 )) {
62 result = false;
63 break;
64 }
65 skipCtor || (skipCtor = key == 'constructor');
66 }
67 if (result && !skipCtor) {
68 var objCtor = object.constructor,
69 othCtor = other.constructor;
70
71 // Non `Object` object instances with different constructors are not equal.
72 if (objCtor != othCtor &&
73 ('constructor' in object && 'constructor' in other) &&
74 !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
75 typeof othCtor == 'function' && othCtor instanceof othCtor)) {
76 result = false;
77 }
78 }
79 stack['delete'](object);
80 return result;
81}
82
83export default equalObjects;