Last active
September 5, 2021 01:43
-
-
Save wesleylhandy/79a82da76d8d8c09da165eab895450d9 to your computer and use it in GitHub Desktop.
Recursive Method to determine if two Object literals are deeply equal.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Recursive function that compares two deeply nested objects to determine if they are identical in their structure and values. | |
* | |
* @param {*} obj1 | |
* @param {*} obj2 | |
* @returns {boolean} Whether or not the two arguments being compared are deeply equal | |
*/ | |
function deepEqual(obj1, obj2) { | |
if (typeof obj1 !== typeof obj2) { | |
return false; | |
} | |
/* FUNCTION */ | |
if (typeof obj1 === 'function') { | |
/* Referential Equality or Identical Implementation */ | |
return (obj1 === obj2) || (obj1.toString() === obj2.toString()); | |
} | |
/* ARRAY */ | |
if (Array.isArray(obj1) && !Array.isArray(obj2)) { | |
return false; | |
} | |
if (Array.isArray(obj1) && obj1.length !== obj2.length) { | |
return false; | |
} | |
if (Array.isArray(obj1)) { | |
let sorted1 = obj1.sort(); | |
let sorted2 = obj2.sort(); | |
for (let i = 0; i < sorted1.length; i++) { | |
if (!deepEqual(sorted1[i], sorted2[i])) { | |
return false | |
} | |
} | |
return true; | |
} | |
/* DATE */ | |
if (obj1 instanceof Date && !obj2 instanceof Date) { | |
return false; | |
} | |
if (obj1 instanceof Date) { | |
return obj1.toString() === obj2.toString(); | |
} | |
/* ERROR */ | |
if (obj1 instanceof Error && !obj2 instanceof Error) { | |
return false; | |
} | |
if (obj1 instanceof Error) { | |
return obj1.toString() === obj2.toString(); | |
} | |
/* REGEXP */ | |
if (obj1 instanceof RegExp && !obj2 instanceof RegExp) { | |
return false; | |
} | |
if (obj1 instanceof RegExp) { | |
return obj1.toString() === obj2.toString(); | |
} | |
/* SET */ | |
if (obj1 instanceof Set && !obj2 instanceof Set) { | |
return false; | |
} | |
if (obj1 instanceof Set && obj1.size !== obj2.size) { | |
return false; | |
} | |
if (obj1 instanceof Set) { | |
let setEntries1 = Array.from(obj1).sort(); | |
let setEntries2 = Array.from(obj2).sort(); | |
for (let i = 0; i < setEntries1.length; i++) { | |
if (!deepEqual(setEntries1[i], setEntries2[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/* MAP */ | |
if (obj1 instanceof Map && !obj2 instanceof Map) { | |
return false; | |
} | |
if (obj1 instanceof Map && obj1.size !== obj2.size) { | |
return false; | |
} | |
if (obj1 instanceof Map) { | |
let mapEntries1 = Array.from(obj1).sort((a, b) => a[0] - b[0]); | |
let mapEntries2 = Array.from(obj2).sort((a, b) => a[0] - b[0]); | |
for (let i = 0; i < mapEntries1.length; i++) { | |
if(!deepEqual(mapEntries1[i], mapEntries2[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/* NULL */ | |
if ((obj1 === null && obj2 !== null) | |
|| (obj1 !== null && obj2 === null)) { | |
return false; | |
} | |
/* OBJECT */ | |
if (typeof obj1 === 'object' && Object.keys(obj1).length !== Object.keys(obj2).length) { | |
return false; | |
} | |
if (typeof obj1 === 'object') { | |
let objEntries1 = Object.entries(obj1); | |
let objEntries2 = Object.entries(obj2); | |
for (let i = 0; i < objEntries1.length; i++) { | |
if (!deepEqual(objEntries1[i], objEntries2[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/* NaN */ | |
if ((Number.isNaN(obj1) && !Number.isNaN(obj2)) | |
|| (!Number.isNaN(obj1) && Number.isNaN(obj2))) { | |
return false | |
} | |
/* PRIMITIVES */ | |
return obj1 === obj2; | |
} | |
module.exports = { deepEqual } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment