_equalObjects.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. var baseHas = require('./_baseHas'),
  2. keys = require('./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`
  15. * for more details.
  16. * @param {Object} stack Tracks traversed `object` and `other` objects.
  17. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
  18. */
  19. function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
  20. var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
  21. objProps = keys(object),
  22. objLength = objProps.length,
  23. othProps = keys(other),
  24. othLength = othProps.length;
  25. if (objLength != othLength && !isPartial) {
  26. return false;
  27. }
  28. var index = objLength;
  29. while (index--) {
  30. var key = objProps[index];
  31. if (!(isPartial ? key in other : baseHas(other, key))) {
  32. return false;
  33. }
  34. }
  35. // Assume cyclic values are equal.
  36. var stacked = stack.get(object);
  37. if (stacked) {
  38. return stacked == other;
  39. }
  40. var result = true;
  41. stack.set(object, other);
  42. var skipCtor = isPartial;
  43. while (++index < objLength) {
  44. key = objProps[index];
  45. var objValue = object[key],
  46. othValue = other[key];
  47. if (customizer) {
  48. var compared = isPartial
  49. ? customizer(othValue, objValue, key, other, object, stack)
  50. : customizer(objValue, othValue, key, object, other, stack);
  51. }
  52. // Recursively compare objects (susceptible to call stack limits).
  53. if (!(compared === undefined
  54. ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
  55. : compared
  56. )) {
  57. result = false;
  58. break;
  59. }
  60. skipCtor || (skipCtor = key == 'constructor');
  61. }
  62. if (result && !skipCtor) {
  63. var objCtor = object.constructor,
  64. othCtor = other.constructor;
  65. // Non `Object` object instances with different constructors are not equal.
  66. if (objCtor != othCtor &&
  67. ('constructor' in object && 'constructor' in other) &&
  68. !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
  69. typeof othCtor == 'function' && othCtor instanceof othCtor)) {
  70. result = false;
  71. }
  72. }
  73. stack['delete'](object);
  74. return result;
  75. }
  76. module.exports = equalObjects;