0

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

2 Answers 2

3

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;
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.