andrew4582

deepEqual

Dec 28th, 2010
365
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Taken from node's assert module, because it sucks
  2. // and exposes next to nothing useful.
  3.  
  4. module.exports = _deepEqual;
  5.  
  6. function _deepEqual(actual, expected) {
  7.   // 7.1. All identical values are equivalent, as determined by ===.
  8.   if (actual === expected) {
  9.     return true;
  10.  
  11.   } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
  12.     if (actual.length != expected.length) return false;
  13.  
  14.     for (var i = 0; i < actual.length; i++) {
  15.       if (actual[i] !== expected[i]) return false;
  16.     }
  17.  
  18.     return true;
  19.  
  20.   // 7.2. If the expected value is a Date object, the actual value is
  21.   // equivalent if it is also a Date object that refers to the same time.
  22.   } else if (actual instanceof Date && expected instanceof Date) {
  23.     return actual.getTime() === expected.getTime();
  24.  
  25.   // 7.3. Other pairs that do not both pass typeof value == "object",
  26.   // equivalence is determined by ==.
  27.   } else if (typeof actual != 'object' && typeof expected != 'object') {
  28.     return actual == expected;
  29.  
  30.   // 7.4. For all other Object pairs, including Array objects, equivalence is
  31.   // determined by having the same number of owned properties (as verified
  32.   // with Object.prototype.hasOwnProperty.call), the same set of keys
  33.   // (although not necessarily the same order), equivalent values for every
  34.   // corresponding key, and an identical "prototype" property. Note: this
  35.   // accounts for both named and indexed properties on Arrays.
  36.   } else {
  37.     return objEquiv(actual, expected);
  38.   }
  39. }
  40.  
  41. function isUndefinedOrNull (value) {
  42.   return value === null || value === undefined;
  43. }
  44.  
  45. function isArguments (object) {
  46.   return Object.prototype.toString.call(object) == '[object Arguments]';
  47. }
  48.  
  49. function objEquiv (a, b) {
  50.   if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
  51.     return false;
  52.   // an identical "prototype" property.
  53.   if (a.prototype !== b.prototype) return false;
  54.   //~~~I've managed to break Object.keys through screwy arguments passing.
  55.   //   Converting to array solves the problem.
  56.   if (isArguments(a)) {
  57.     if (!isArguments(b)) {
  58.       return false;
  59.     }
  60.     a = pSlice.call(a);
  61.     b = pSlice.call(b);
  62.     return _deepEqual(a, b);
  63.   }
  64.   try{
  65.     var ka = Object.keys(a),
  66.       kb = Object.keys(b),
  67.       key, i;
  68.   } catch (e) {//happens when one is a string literal and the other isn't
  69.     return false;
  70.   }
  71.   // having the same number of owned properties (keys incorporates hasOwnProperty)
  72.   if (ka.length != kb.length)
  73.     return false;
  74.   //the same set of keys (although not necessarily the same order),
  75.   ka.sort();
  76.   kb.sort();
  77.   //~~~cheap key test
  78.   for (i = ka.length - 1; i >= 0; i--) {
  79.     if (ka[i] != kb[i])
  80.       return false;
  81.   }
  82.   //equivalent values for every corresponding key, and
  83.   //~~~possibly expensive deep test
  84.   for (i = ka.length - 1; i >= 0; i--) {
  85.     key = ka[i];
  86.     if (!_deepEqual(a[key], b[key] ))
  87.        return false;
  88.   }
  89.   return true;
  90. }
Advertisement
Add Comment
Please, Sign In to add comment