_equalObjects.js 2.9 KB

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