Skip to content

Home

Check if two JavaScript objects have the same properties

Given two JavaScript objects, it's not straightforward to compare them for equality. This is because objects are reference types, and two objects with the same properties and values are not considered equal. However, it's not difficult to implement a function that does just that.

One-sided comparison

First off, let's create a function that compares two objects to determine if the first one contains equivalent property values to the second one. This essentially means checking if the keys of the first object are a superset of the keys of the second object, and if the values of the first object are equal to the values of the second object.

Comparing objects this way requires iterating over the keys of the second object, using Object.keys(), and checking if each key exists in the first object using Array.prototype.every(), Object.prototype.hasOwnProperty().

Comparison by value

In order to compare the values of the properties, we can simply use the strict equality operator (===). This will ensure that the values are not only equal but also of the same type.

const matches = (obj, source) =>
  Object.keys(source).every(
    key => obj.hasOwnProperty(key) && obj[key] === source[key]
  );

matches(
  { age: 25, hair: 'long', beard: true },
  { hair: 'long', beard: true }
); // true

matches(
  { hair: 'long', beard: true },
  { age: 25, hair: 'long', beard: true }
); // false

Comparison using a custom function

If, instead, we want to use a custom function to determine value equality, we can simply replace the strict equality operator with the provided function. This function will receive the value of the property in both objects, as well as the key and the objects themselves.

const matchesWith = (obj, source, fn) =>
  Object.keys(source).every(
    key =>
      obj.hasOwnProperty(key) &&
      fn(obj[key], source[key], key, obj, source)
  );

const isGreeting = val => /^h(?:i|ello)$/.test(val);
matchesWith(
  { greeting: 'hello' },
  { greeting: 'hi' },
  (a, b) => isGreeting(a) && isGreeting(b)
); // true

Two-sided comparison

If you want to compare two objects in both directions, you can create a Set of the keys of both objects and check if the size of the set is equal to the number of keys in each object. Then, you can use the same approach as before, except iterating over the keys of the set and checking if each key exists in both objects.

Comparison by value

For simple value comparison, you can again use the strict equality operator (===).

const matchesSymmetric = (a, b) => {
  const keysA = Object.keys(a),
    keysB = Object.keys(b);
  const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
  if (keys.size !== keysA.length || keys.size !== keysB.length) return false;

  return [...keys].every(
    key => a.hasOwnProperty(key) && b.hasOwnProperty(key) && a[key] === b[key]
  );
};

matchesSymmetric(
  { age: 25, hair: 'long', beard: true },
  { hair: 'long', beard: true }
); // false

matchesSymmetric(
  { hair: 'long', beard: true },
  { age: 25, hair: 'long', beard: true }
); // false

matchesSymmetric(
  { age: 25, hair: 'long', beard: true },
  { age: 25, hair: 'long', beard: true }
); // true

Comparison using a custom function

For custom value comparison, you can use the same approach as before, using a custom function to determine value equality.

const matchesSymmetricWith = (a, b, fn) => {
  const keysA = Object.keys(a),
    keysB = Object.keys(b);
  const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
  if (keys.size !== keysA.length || keys.size !== keysB.length) return false;

  return [...keys].every(
    key =>
      a.hasOwnProperty(key) &&
      b.hasOwnProperty(key) &&
      fn(a[key], b[key], key, a, b)
  );
};

const isGreeting = val => /^h(?:i|ello)$/.test(val);
matchesSymmetricWith(
  { greeting: 'hello', other: 2 },
  { greeting: 'hi' },
  (a, b) => isGreeting(a) && isGreeting(b)
); // false

matchesSymmetricWith(
  { greeting: 'hello' },
  { greeting: 'hi' },
  (a, b) => isGreeting(a) && isGreeting(b)
); // true

More like this

Start typing a keyphrase to see matching snippets.