isEqual.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. var isFn = require('./isFn');
  2. var has = require('./has');
  3. var keys = require('./keys');
  4. exports = function(a, b) {
  5. return eq(a, b);
  6. };
  7. function deepEq(a, b, aStack, bStack) {
  8. var className = toString.call(a);
  9. if (className !== toString.call(b)) return false;
  10. switch (className) {
  11. case '[object RegExp]':
  12. case '[object String]':
  13. return '' + a === '' + b;
  14. case '[object Number]':
  15. if (+a !== +a) return +b !== +b;
  16. return +a === 0 ? 1 / +a === 1 / b : +a === +b;
  17. case '[object Date]':
  18. case '[object Boolean]':
  19. return +a === +b;
  20. }
  21. var areArrays = className === '[object Array]';
  22. if (!areArrays) {
  23. if (typeof a != 'object' || typeof b != 'object') return false;
  24. var aCtor = a.constructor;
  25. var bCtor = b.constructor;
  26. if (
  27. aCtor !== bCtor &&
  28. !(
  29. isFn(aCtor) &&
  30. aCtor instanceof aCtor &&
  31. isFn(bCtor) &&
  32. bCtor instanceof bCtor
  33. ) &&
  34. 'constructor' in a &&
  35. 'constructor' in b
  36. )
  37. return false;
  38. }
  39. aStack = aStack || [];
  40. bStack = bStack || [];
  41. var length = aStack.length;
  42. while (length--) if (aStack[length] === a) return bStack[length] === b;
  43. aStack.push(a);
  44. bStack.push(b);
  45. if (areArrays) {
  46. length = a.length;
  47. if (length !== b.length) return false;
  48. while (length--)
  49. if (!eq(a[length], b[length], aStack, bStack)) return false;
  50. } else {
  51. var _keys = keys(a);
  52. var key;
  53. length = _keys.length;
  54. if (keys(b).length !== length) return false;
  55. while (length--) {
  56. key = _keys[length];
  57. if (!(has(b, key) && eq(a[key], b[key], aStack, bStack)))
  58. return false;
  59. }
  60. }
  61. aStack.pop();
  62. bStack.pop();
  63. return true;
  64. }
  65. function eq(a, b, aStack, bStack) {
  66. if (a === b) return a !== 0 || 1 / a === 1 / b;
  67. if (a == null || b == null) return a === b;
  68. if (a !== a) return b !== b;
  69. var type = typeof a;
  70. if (type !== 'function' && type !== 'object' && typeof b != 'object')
  71. return false;
  72. return deepEq(a, b, aStack, bStack);
  73. }
  74. module.exports = exports;