Hiprup

How do you implement a deep comparison function?

Deep equality checks whether two values are structurally identical at every level.

  1. If both are strictly equal, they're equal (handles primitives).

  2. If either isn't an object (or one is null), they're unequal.

  3. Compare their key counts; if different, unequal.

  4. Recursively compare each property's values.

Edge cases: arrays vs objects, null, and circular references.

function deepEqual(a, b) {
  // Same reference or same primitive
  if (a === b) return true;

  // Handle null/undefined
  if (a == null || b == null) return false;

  // Different types
  if (typeof a !== typeof b) return false;

  // Primitives already checked by ===
  if (typeof a !== 'object') return false;

  // Arrays
  if (Array.isArray(a) !== Array.isArray(b)) return false;
  if (Array.isArray(a)) {
    if (a.length !== b.length) return false;
    return a.every((val, i) => deepEqual(val, b[i]));
  }

  // Date
  if (a instanceof Date && b instanceof Date) {
    return a.getTime() === b.getTime();
  }

  // Objects
  const keysA = Object.keys(a);
  const keysB = Object.keys(b);
  if (keysA.length !== keysB.length) return false;
  return keysA.every(key => deepEqual(a[key], b[key]));
}

// Tests
console.log(deepEqual({a: 1, b: {c: 2}}, {a: 1, b: {c: 2}})); // true
console.log(deepEqual([1, [2, 3]], [1, [2, 3]]));               // true
console.log(deepEqual({a: 1}, {a: 2}));                         // false
console.log(deepEqual(new Date('2024-01-01'), new Date('2024-01-01'))); // true

Base cases: same reference (===), null/undefined, different types. Array: compare lengths then elements recursively. Date: compare timestamps.

Objects: compare key counts then each value recursively. This covers most common types — a production version would also handle Map, Set, RegExp, and circular references.

Handle in order: same reference, null, different types, arrays (length + every), Dates (getTime), objects (keys + recursive). This is a common interview coding question.

Mention limitations: does not handle Map, Set, circular references. lodash.isEqual handles everything.

How do you implement a deep comparison function? | Hiprup