back to series

Implement a deepEqual function

The Object.is() static method determines whether two values are the same values or not in JavaScript.

Same values in JavaScript can mean different things based on how they are compared. You can read about equality comparisons and sameness from this MDN reference.

We are to implement a deepEqual function which recursively checks if two values are same or not, i.e hold the same value. It can take any JSON-serializable values.

1. Basic implementation

./src/deepEqual.js
import isPojo from './src/utils.js';
function deepEqual(inputA, inputB) {
const typeOfA = typeof inputA;
const typeOfB = typeof inputB;
// if type is not same, they can't be equal
if (typeOfA !== typeOfB) {
return false;
}
// if both are arrays
if (Array.isArray(inputA) && Array.isArray(inputB)) {
if (inputA.length !== inputB.length) {
return false;
}
return Array.prototype.every.call(inputA, (itemInA, index) => deepEqual(itemInA, inputB[index]));
}
// if both are objects
if (isPojo(inputA) && isPojo(inputB)) {
// we are using Object.key since we are only interested in objects own properties
const keysA = Object.keys(inputA);
const keysB = Object.keys(inputB);
if (keysA.length !== keysB.length) {
return false;
}
const everyKeysSame = keysA.every((key) => keysB.includes(key));
if (!everyKeysSame) {
return false;
}
return Array.prototype.every.call(keysA, (keyInA) => deepEqual(inputA[keyInA], inputB[keyInA]));
}
// other primitive values
return Object.is(inputA, inputB);
}
// Usage
console.log(deepEqual(1, 1)); // yields true
console.log(deepEqual(1, '1')); // yields false
console.log(deepEqual(null, null)); // yields true
console.log(
deepEqual(
[1, 2, '3', [2, 4, '9', { a: 1, b: 2, c: 'hi' }]], // nested inputs
[1, 2, '3', [2, 4, '9', { b: 2, c: 'hi', a: 1 }]]
)
); // yields true

In the above implementation , I have used a utility called isPojo(), which essentially checks if the given value is a Plain Old JavaScript Object or not. It can be implemented as follows:

./src/isPojo.js
function isPojo(value) {
if (value != null) {
const prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
}
return false;
}

Further Reading

I strongly encourage you to explore and tackle additional questions in my Recursion Questions for Frontend Interviews blog series.

By doing so, you can enhance your understanding and proficiency with recursion, preparing you to excel in your upcoming frontend interviews.

Wishing you best. Happy Interviewing 🫡.