The task is to implement deep equal _isEqual.
The boilerplate code
function isEqual(a, b) {
// your code here
}
Handle primitive and reference equality
if (Object.is(a, b)) return true;
Reject non-objects early
if(typeof a !== "object" || typeof b !== 'object' || a === null || b === null) {
return false;
}
Track pairs already compared
const key = `${a}:${b}`;
if (seen.has(key)) {
return true;
}
seen.set(key, true);
Compare time values. Two different Date values can be equal
if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
}
Compare patterns and flags
if (a instanceof RegExp && b instanceof RegExp) {
return a.toString() === b.toString();
}
Sort objects that represent different structures
if (Array.isArray(a) !== Array.isArray(b)) return false;
Objects with different numbers of properties cannot be equal
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) {
seen.delete(key);
return false;
}
seen.delete(key) ensures cleanup on failure.
Each property in one object must be present in the other. Each value should be compared recursively
for (const key of keysA) {
if (!keysB.includes(key)) {
seen.delete(key);
return false;
}
if (!isEqual(a[key], b[key], seen)) {
seen.delete(key);
return false;
}
}
The final code
function isEqual(a, b, seen = new Map()) {
// your code here
if(Object.is(a,b)) return true;
if(typeof a !== "object" || typeof b !== 'object' || a === null || b === null) {
return false;
}
const key = `${a}:${b}`;
if(seen.has(key)) {
return true;
}
seen.set(key,true);
if(a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
}
if(a instanceof RegExp && b instanceof RegExp) {
return a.toString() === b.toString()
}
if(Array.isArray(a) !== Array.isArray(b)) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if(keysA.length !== keysB.length) {
seen.delete(key);
return false;
};
for(const key of keysA) {
if(!keysB.includes(key)){
seen.delete(key);
return false;
};
if(!isEqual(a[key], b[key], seen)) {
seen.delete(key);
return false;
};
}
seen.delete(key);
return true;
}
That's all folks!
Top comments (0)