Reputation: 667
Am reading Eloquent javascript and I was given a task to write a deep equal function for objects.
My code works well for object without nested object but when i pass two object that has a nested object in it my code fails.
i tried debugging it and i noticed that anytime the function encounters a nested object, it doesn't transfer control back to the main object.
Take for example i have two object a and b below:
let a = {
name: "ade",
last: "segun",
dead: {
name: "ade",
last: "segun",
},
eaten: true,
};
let b = {
name: "ade",
last: "segun",
dead: {
name: "ade",
last: "segun",
},
eaten: false,
};
After the function checks for the dead property which is a nested object, it doesn't return to the main object and checks for eaten
property.
What did I do wrong? This is My code
let a = { name: "ade", last: "segun", dead: { name: "ade", last: "segun", }, eaten: true, };
let b = { name: "ade", last: "segun", dead: { name: "ade", last: "segun", }, eaten: false, };
const deepEqual = (obj1, obj2) => {
const keysA = Object.keys(obj1);
const keysB = Object.keys(obj2);
if (keysA.length !== keysB.length) {
return false;
}
let c;
for (let key of keysA) {
// c checks whether the key is part of keysB array
c = keysB[keysB.indexOf(key)];
if (key !== c) {
return false;
}
if (
typeof obj1[key] === "object" &&
typeof obj2[c] === "object" &&
obj1[key] !== null &&
obj2[c] !== null
) {
return deepEqual(obj1[key], obj2[c]);
} else {
if (obj1[key] !== obj2[c]) return false;
}
}
return true;
};
console.log(deepEqual(a, b)); //true
Upvotes: 0
Views: 2814
Reputation: 39
Thanks for your code. You saved me so much time. Exactly what I needed. But my implementation was to find the deep difference between two objects.
I just had to edit the code a little. I will drop it for someone that might have the same issue I was trying to solve
const differenceObj = {
};
const deepEqual = (obj1: any, obj2: any) => {
const keysA = Object.keys(obj1);
const keysB = Object.keys(obj2);
if (keysA.length !== keysB.length) {
return false;
}
let c;
for (const key of keysA) {
c = keysB[keysB.indexOf(key)];
if (key !== c) {
return false;
}
if (
typeof obj1[key] === 'object' &&
typeof obj2[c] === 'object' &&
obj1[key] !== null &&
obj2[c] !== null
) {
deepEqual(obj1[key], obj2[c]);
}
if (obj1[key] !== obj2[c]) {
differenceObj[key] = {
new: obj1[key],
old: obj2[key],
};
}
}
return differenceObj;
}
I had to return the old and the new values which represents the differences.
Upvotes: 0
Reputation: 106385
This line in your code...
return deepEqual(obj1[key], obj2[c]);
... basically makes the comparison function to stop when the first nested object is encountered. What should happen instead is 1) result of deepEqual is calculated, and 2) only if it's false
, the function returns it immediately. For example:
const isDeeplyEqual = deepEqual(obj1[key], obj2[c]);
if (!isDeeplyEqual) return false;
... or just:
if (!deepEqual(obj1[key], obj2[c])) return false;
Upvotes: 3