Chunky Chunk
Chunky Chunk

Reputation: 17217

Deep Object Compare using Recursion

I'm attempting deep object comparison using recursion, but my function is returning undefined.

I know there are better ways to compare objects (IE JSON.Stringify()) but I'm not understanding why my function is returning undefined.

function deepObjCompare(obj1, obj2) {

  Object.keys(obj1).forEach((key) => {
    const key1 = obj1[key];
    const key2 = obj2[key];

    if (key2) {
      if (typeof key1 === "object" && key1 !== null) {
        deepObjCompare(key1, key2);
      } else if (key1 === key2) {
        return true;
      }
    }
    return false;
  });
}

const obj1 = {
  name: "Bill",
  address: {
    cityNow: "Paris",
    cityFuture: "NYC"
  },
  age: 39
};

const obj2 = {
  name: "Bill",
  address: {
    cityNow: "Paris",
    cityFuture: "NYC"
  },
  age: 39
};

const obj3 = {
  name: "Bob",
  address: "Paris",
  age: 39
};

console.log(deepObjCompare(obj1, obj3));

Upvotes: 1

Views: 79

Answers (3)

Luca Kiebel
Luca Kiebel

Reputation: 10096

You can't return from a forEach loop, and you have to return the recursive call:

function deepObjCompare(obj1, obj2) {

  let keys = Object.keys(obj1);
  return keys.every((key) => { // use a for-of loop instead of forEach
    const key1 = obj1[key];
    const key2 = obj2[key];

    if (key2) {
      if (typeof key1 === "object" && key1 !== null) {
         return deepObjCompare(key1, key2); // return the recursive call
      } else if (key1 === key2) {
        return true;
      }
    }
    return false;
  });
}

const obj1 = {name: "Bill",address: {cityNow: "Paris",cityFuture: "NYC"},age: 39};
const obj2 = {name: "Bill",address: {cityNow: "Paris",cityFuture: "NYC"},age: 39};
const obj3 = {name: "Bill",address: "Paris",age: 39};

console.log("Are Obj1 and Obj3 equal? ",deepObjCompare(obj1, obj3));
console.log("Are Obj1 and Obj2 equal? ",deepObjCompare(obj1, obj2));

Upvotes: 2

Robin Zigmond
Robin Zigmond

Reputation: 18249

There are actually a number of things I see that are wrong with this implementation. But as to why it's returning undefined - that's because your function never actually returns anything. All your return statements are inside the function passed to forEach, and therefore do nothing with regard to the outer deepObjCompare.

Upvotes: -1

CRice
CRice

Reputation: 32166

I see three main issues here:

  • deepObjCompare lacks a return statement, which is why it is implicitly returning undefined.
  • The .forEach method always returns undefined, so you'll want to change that to another method that will return an actual value. I think .every is what you're after here.
  • You do not return the result of your recursive call.

All together, that would change your snippet to the following:

function deepObjCompare(obj1, obj2) {

  return Object.keys(obj1).every((key) => { // Use .every and return the result!
    const key1 = obj1[key];
    const key2 = obj2[key];

    if (key2) {
      if (typeof key1 === "object" && key1 !== null) {
        return deepObjCompare(key1, key2); // Return the result of your recursive call!
      } else if (key1 === key2) {
        return true;
      }
    }
    return false;
  });
}

const obj1 = {
  name: "Bill",
  address: {
    cityNow: "Paris",
    cityFuture: "NYC"
  },
  age: 39
};

const obj2 = {
  name: "Bill",
  address: {
    cityNow: "Paris",
    cityFuture: "NYC"
  },
  age: 39
};

const obj3 = {
  name: "Bob",
  address: "Paris",
  age: 39
};

console.log(deepObjCompare(obj1, obj3)); // false
console.log(deepObjCompare(obj1, obj2)); // true

Upvotes: 2

Related Questions