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

I admit, this is one of my go‑to interview questions when looking to hire new front‑end 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 50‑50 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 built‑in 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
For arrays and plain objects, including cyclic structures, a deliberately scoped comparison utility might look like this:
const deepEqualPlainData = (left, right, seen = new WeakMap()) => { if (left === right) return true; if ( typeof left !== 'object' || left === null || typeof right !== 'object' || right === null ) { return false; } const leftPrototype = Object.getPrototypeOf(left); const rightPrototype = Object.getPrototypeOf(right); const isSupported = Array.isArray(left) || leftPrototype === Object.prototype || leftPrototype === null; if (!isSupported || leftPrototype !== rightPrototype) return false; if (seen.has(left)) return seen.get(left) === right; seen.set(left, right); const leftKeys = Reflect.ownKeys(left); const rightKeys = Reflect.ownKeys(right); if (leftKeys.length !== rightKeys.length) return false; for (const key of leftKeys) { if (!Object.prototype.hasOwnProperty.call(right, key)) return false; if (!deepEqualPlainData(left[key], right[key], seen)) return false; } return true;};const obj1 = { a: 1, b: { c: 1 } };const obj2 = { a: 1, b: { c: 1 } };console.log(deepEqualPlainData(obj1, obj2)); //=> trueconst obj3 = { a: 1, b: { c: 2 } };console.log(deepEqualPlainData(obj1, obj3)); //=> falseThis helper deliberately accepts only arrays and plain objects. It compares every own key, including symbols, and records object pairs in a WeakMap so cycles terminate. Date, RegExp, Map, Set, class instances and other specialised objects need type‑specific comparison or a well‑tested library.
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)); //=> trueWrapping 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.