Link to home
Start Free TrialLog in
Avatar of dancablam
dancablam

asked on

Comparing Objects in JavaScript

Hi Guys,

Does anyone have a good method that can returns true if all values in one object match that in another object? (it needs to support recursion too)

Ex:
var o1 = {
  item1:123
  item2: {
    item3: 456
  }
}
var o2 = {
  item1:123
  item2: {
    item3: 456
  }
}
var o3 = {
  item1:123
  item2: {
    item3: 'ABC'
  }
}

So when comparing o1 to o2 the method would eval to true, comparing o1 to o3 would eval to false.

Cheers,
Dan
Avatar of HonorGod
HonorGod
Flag of United States of America image

That might be difficult.  Consider the scenario where the object contains a "this" reference.
The eval would only be able to return true if the objects being compared refer to a single object.
A simple test to see if two variables reference the same object would be to use the === operator.


function same( a, b ) {
  return a === b;
}

Open in new window

Avatar of dancablam
dancablam

ASKER

The objects will only contain data - not methods. Also they won't be referencing the same object so the === won't work. I simply need a method to walk recursively down an object and see if all the property/value combinations match.
This will work for objects that both have the same values:
function compareObj(obj1,obj2) {
    // if obj1 and obj2 are not both objects, return simple comparison
    if (typeof obj1 != 'object' || typeof obj2 != 'object') { return (obj1==obj2); }
    // compare indexes in obj1 with those in obj2
    for (index in obj1) {
      var item1 = obj1[index];
      var item2 = obj2[index];
      if (typeof item1 == 'object') if (!compareObj(item1,item2)) return false;
      if (typeof item1 != 'object') if (item1!=item2) return false;
    }
    // if we got this far, the are the same
    return true;
} 
 
// demo
var o1 = { item1:123, item2: { item3: 456 } };
var o2 = { item1:123, item2: { item3: 456 } };
var o3 = { item1:123, item2: { item3: 'ABC' } };
alert(compareObj(o1,o2));
alert(compareObj(o1,o3));

Open in new window

Clarification. The above code will work for objects that both have the same properties. Example:
// comparing these two will work
var o1 = { item1:'abc' }
var o2 = { item1:'def' }
// but comparing these two won't always work properly
var o1 = { item1:'abc' }
var o2 = { item1:'def',item2:'xyz' }

Open in new window

Something like this perhaps?
<html>
<body>
 
<script type="text/javascript">
var o1 = {
  item1 : 123,
  item4 : 'Hi',
  item2 : { item3 : 456 }
}
var o2 = {
  item1 : 123,
  item4 : 'hi',
  item2 : { item3 : 456 }
}
var o3 = {
  item1 : 123,
  item4 : 'Hi',
  item2 : { item3 : 'ABC' }
}
 
function oCompare( o1, o2 ) {
  var result = false;
  if ( typeof( o1 ) == typeof( o2 ) ) {
    if ( typeof( o1 ) == 'object' ) {
      if ( o1 === o2 ) {
        return true;
      } else {
        for ( p in o1 ) {
          if ( p in o2 ) {
            var T = typeof( o1[ p ] );
            if ( T == typeof( o2[ p ] ) ) {
              switch ( T ) {
                case 'boolean' : if ( o1[ p ] != o2[ p ] ) return false;
                  break;
                case 'number' : if ( o1[ p ] != o2[ p ] ) return false;
                  break;
                case 'function' : if ( o1[ p ] !== o2[ p ] ) return false;
                  break;
                case 'string' : if ( o1[ p ] != o2[ p ] ) return false;
                  break;
                case 'object' : if ( !oCompare( o1[ p ], o2[ p ] ) ) return false;
                  break;
                default:
                  alert( 'p: ' + p + ' typeof: ' + T );
              }
            } else {
              return false;
            }
          } else {
            return false;
          }
        }
      }
    }
  }
  return result;
}
 
document.write( oCompare( o1, o3 ) );
 
</script>
 
</body>
</html>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of HonorGod
HonorGod
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for accepting my solution.

I'm sorry that you didn't feel that it was worthy of an A.

Good luck & have a great day.