Skip to content

Instantly share code, notes, and snippets.

@wesleylhandy
Last active September 5, 2021 01:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wesleylhandy/79a82da76d8d8c09da165eab895450d9 to your computer and use it in GitHub Desktop.
Save wesleylhandy/79a82da76d8d8c09da165eab895450d9 to your computer and use it in GitHub Desktop.
Recursive Method to determine if two Object literals are deeply equal.
/**
* 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