Object Equality in JavaScript: {} isn't Equal to {}

Hero image for Object Equality in JavaScript: {} isn't Equal to {}. Image by Elena Koycheva.
Hero image for 'Object Equality in JavaScript: {} isn't Equal to {}.' Image by Elena Koycheva.

I admit, this is one of my goto interview questions when looking to hire new frontend developers into one of my teams (something that I've been doing a lot of recently). The question is simple. Given the code below, can you explain why a == b will return false?

let a = {};let b = {};

On the surface of this, it does seem like both a and b should be equal. I tend to find that it is around 5050 whether an interviewer understands the reason behind why these two empty objects aren't equal. It also helpfully tends to identify those candidates whose experience lies more in relying on helpers and frameworks rather than understanding the more fundamental aspects of JavaScript and data types.


Understanding Object Identity

The answer to this question lies in how JavaScript handles object comparison. When comparing objects, JavaScript doesn't look at their contents or structure (as it might do with an equality operator on a simple number, boolean, or string variable). Instead, it looks at the object identities it checks if the objects being compared are exactly the same instance.

In our example, a and b are different objects, each with their own unique references within memory. Even though they have the same structure and content (i.e., empty), they are considered distinct entities within the JavaScript engine. This is a fairly fundamental concept which underpins a lot of JavaScript's behaviour when it comes to objects and their comparison.


Deep Comparison for Objects

If you are ever asked this question in an interview and really want to earn a few extra points, then being able to explain how you would compare two objects (and their contents) would certainly achieve that. JavaScript doesn't offer a builtin operator for this, but that doesn't mean that it's particularly difficult or a dead end.

You can perform a deep comparison by writing a function that iteratively checks each property and value within the objects or by using utilities provided by libraries like Lodash, which offer methods specifically designed for this purpose.

In JavaScript

If you were to write a utility function to deeply compare two objects, it might look something like this:

const deepEqual = (obj1: any, obj2: any): boolean => {  if (obj1 === obj2) {    return true;  }  if (    typeof obj1 !== 'object' || obj1 === null ||    typeof obj2 !== 'object' || obj2 === null  ) {    return false;  }  const keys1: string[] = Object.keys(obj1);  const keys2: string[] = Object.keys(obj2);  if (keys1.length !== keys2.length) {    return false;  }  for (let key of keys1) {    if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {      return false;    }  }  return true;};const obj1 = { a: 1, b: { c: 1 } };const obj2 = { a: 1, b: { c: 1 } };console.log(deepEqual(obj1, obj2));  //=> trueconst obj3 = { a: 1, b: { c: 2 } };console.log(deepEqual(obj1, obj3));  //=> false

What this does is firstly check if both parameters are objects. If they are, we then compare their keys and values. Where it comes across a property that is itself an object, it calls itself recursively, comparing all the way down to the deepest level.

Using Lodash

Alternatively, if you prefer using a library (or if you already have Lodash as a dependency in your project), then the isEqual method will already do this for you:

import isEqual from 'lodash/isEqual';const obj1 = { a: 1, b: { c: 1 } };const obj2 = { a: 1, b: { c: 1 } };console.log(isEqual(obj1, obj2));  //=> true

Wrapping up

Although comparing {} with {} and getting false might feel counterintuitive, this is an area that unveils a candidate's understanding of JavaScript's approach to object identity and comparison. Although only a tiny piece of what makes a good developer, this is a concept that is really important when it comes to writing efficient and optimised code. In the realm of objects in JavaScript, identity precedes equality.


Categories:

  1. Front‑End Development
  2. Guides
  3. JavaScript