equalObjects.js 2.6 KB

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