Comprehensive Guide to Comparing Objects in JavaScript

November 9, 2024
:89  :0

Object Comparison Methods in JavaScript

1. The instanceof Operator

The instanceof operator checks if an object is an instance of a particular constructor function by examining the prototype chain.

Syntax

object instanceof Constructor

Key Characteristics

  • Returns true if Constructor.prototype exists in the object's prototype chain
  • Works only with reference types (objects), not primitive values
  • Affected by prototype modifications

Examples

class Person {}
const john = new Person();

console.log(john instanceof Person);  // true
console.log(john instanceof Object); // true

const arr = [1, 2, 3];
console.log(arr instanceof Array);   // true

Limitations

// Doesn't work with primitives
console.log('test' instanceof String); // false

// Cross-realm issues (e.g., iframes)
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console.log([] instanceof iframe.contentWindow.Array); // false

2. Object.keys() vs Object.entries()

MethodReturnsUse Case
Object.keys()Array of property namesWhen you only need keys
Object.entries()Array of [key, value] pairsWhen you need both keys and values

Practical Examples

Using Object.keys()

const user = { name: 'Alice', age: 30 };

Object.keys(user).forEach(key => {
  console.log(`${key}: ${user[key]}`);
});
// Output:
// name: Alice
// age: 30

Using Object.entries()

for (const [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`);
}
// Same output as above

3. Deep Object Comparison with Lodash

Lodash's _.isEqual() performs deep equality comparison, making it ideal for comparing complex objects.

Basic Usage

const _ = require('lodash');

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };

console.log(_.isEqual(obj1, obj2)); // true

Advanced Techniques

  1. Partial Comparison
const partialCompare = (obj1, obj2, keys) => 
  _.isEqual(_.pick(obj1, keys), _.pick(obj2, keys));

console.log(partialCompare(
  { a: 1, b: 2, c: 3 },
  { a: 1, b: 4, c: 3 },
  ['a', 'c']
)); // true
  1. Custom Comparator
function customizer(objValue, othValue) {
  if (_.isNumber(objValue) && _.isNumber(othValue)) {
    return Math.abs(objValue - othValue) < 0.5;
  }
}

console.log(_.isEqualWith(
  { x: 1.2, y: 2 },
  { x: 1.4, y: 2 },
  customizer
)); // true

Performance Considerations

MethodTime ComplexityBest For
instanceofO(1)Prototype checks
Object.keysO(n)Simple objects
_.isEqualO(n)Deep comparison

Native Alternatives (ES6+)

For shallow comparison:

const shallowEqual = (obj1, obj2) => 
  Object.keys(obj1).length === Object.keys(obj2).length &&
  Object.keys(obj1).every(key => obj1[key] === obj2[key]);

For JSON-compatible objects:

const jsonEqual = (obj1, obj2) => 
  JSON.stringify(obj1) === JSON.stringify(obj2);
  1. Use instanceof for class/prototype checks
  2. Use Object.keys/Object.entries for shallow property inspection
  3. Use Lodash's _.isEqual for deep comparison
  4. For custom needs, implement specialized comparators

Pro Tip: When using Lodash, import only needed functions to reduce bundle size:

import isEqual from 'lodash/isEqual';

Explore more comparison techniques on MDN