How to Compare Objects in JavaScript
Tags: javascript, webdev, programming, beginners
Published: 2022-06-02 22:56:57

Today, I am going to show you a basic way to write a function that compares (2) objects, and also retrieves their matching properties.

## compareObject

This function as the name states will be used to compare 2 objects and it works for objects that contain simple, but not complex properties.

> A complex property, in this case, can be seen as a property in which their values contain arrays or other objects within them.

## Quick Memory Refresh on Objects

Before we begin, let us refresh our memory on JavaScript Objects.

![js-object.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645394229881/8Ka52jmlS.png)

Say, we have the object below;

```javascript
const user = {
    "uid" : 12345,
    "name" : "simon",
    "loc" : "NG"
}

```
To access the value of any property, we will make use of the key.

To list out all keys contained in this Object, we will do something like this;

```javascript
console.log(Object.keys(user));
/* ['uid', 'name', 'loc'] */

``` 
Now, depending on the property we wish to access, we will make use of their respective keys to access them.

Let's access the user's uid (user_id), name, and location.

```javascript
console.log(user['uid']);
//12345
console.log(user['name']);
//Simon
console.log(user['loc']);
//NG

```
Since we can't directly use the **length** method to find out how many properties are contained in the object, we have to list out the keys first and then find out how many keys were listed out. In this way, we have the total properties contained in the object.

```javascript
console.log(Object.keys(user).length);
//3

```

Having a basic knowledge of objects, let's write our function that compares two objects and **returns** **true** if they are equal, and **false** if they are not.

We will start off by checking if the parameters provided are Objects.

The arrow function below returns **true** if it is an object or **false** if not.

```javascript
const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
}
```

Then we check if the length of the first object equals the length of the second object.

This is because when comparing two things, in this case, Objects, they must have equal lengths and equal properties.

```javascript
function compareObject(obj1, obj2){
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length; //use any length
    }

}

```
Now, we will loop through the first object, to compare its properties (key and value), one by one with the second object.

We will also create a variable that stores the number of matched properties, and then we will check if the number of matched properties equals the length of the object. If they are equal, we will return **true** which means that the two objects provided are equal.

```javascript
function compareObject(obj1, obj2){
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length; //use any length
    }

    let match = 0; //store number of matched properties
    Object.keys(obj1).forEach(i => {
        //check if values with the same keys are equal
        if(obj1[i] === obj2[i]){
            match++; //increment the variable
        }
    })
    //check if length equals the number of matched properties
    if(match === len){
        return true;
    }

    return false;
}

```
### Testing our compareObject Function

In other to test this function, we will create 4 Objects. Two Objects will contain the same properties (a and d) and the other two will contain unequal properties (b and c). Then we will call the function and pass in the variables.

Here's the full script

```javascript
const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
}

function compareObject(obj1, obj2){
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length; //use any length
    }

    let match = 0; //store number of matched properties
    Object.keys(obj1).forEach(i => {
        //check if values with the same keys are equal
        if(obj1[i] === obj2[i]){
            match++; //increment the variable
        }
    })
    //check if object length equals the number of matched properties
    if(match === len){
        return true;
    }

    return false;
}
```
Let's call the function

```javascript
const a = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}
const b = {"name" : "ugorji", "age" : 6, "loc" : 'NG', "sex" : "male"}
const c = {"name" : "okorie", "age" : 7, "loc" : 'NG', "sex" : "male"}
const d = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}

//check b and c -> unequal
compareObject(b, c);

//check a and d -> equal
compareObject(a, d);

```
#### Comparing b and c

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645391438663/_702YU5PTI.png)

#### Comparing a and d

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645391497442/oGA1Z7EiW.png)

### What Next?

We have completed our function that checks if two objects are equal. It returns **true** if equal and **false** if unequal. We can extend the function to list out properties that are contained in both objects.

We can use this to list out the matching properties contained in the objects.

#### Let us edit our function

We will create a variable of type **object**, that will store the matched properties (ie. properties contained in the first object and in the second object).

Then inside the block that confirms if both properties are equal, we will append the key and value of the matched property.

```javascript
function compareObject(obj1, obj2){
    //comparing obj with obj2
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length;
    }

    //check against obj2
    let i = 0;
    let match = 0;
    //store matched properties
    let matchVal = {};
    Object.keys(obj1).forEach(i => {
        if(obj1[i] === obj2[i]){
            match++; //increment the variable
            //append key and value to the variable
            matchVal[i] = obj1[i];
        }
    })
    console.log(matchVal); //show the matched properties
    //check if the number of properties matched = the length of the object
    if(match == len){
        return true;
    }

    return false;
}

```
Now let us test the function again by comparing the previous unequal objects. The function should list out the matched properties of the two objects, and *return false* since they are unequal.

```javascript
const a = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}
const b = {"name" : "ugorji", "age" : 6, "loc" : 'NG', "sex" : "male"}
const c = {"name" : "okorie", "age" : 7, "loc" : 'NG', "sex" : "male"}
const d = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}

//check unequal objects
compareObject(b, c);

```
#### comparing objects b and c

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645392678203/RpmQlZrNQ.png)

It works!!!

## Wrapping Up

If your Object's property contains a value that is either an object or an array, the comparison operator (===) will return false because we can't directly compare 2 objects or arrays using the operator.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645393312815/lLfu9Bn8w.png)

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645393393689/PnrMje7uf.png)

In this case, you will have to check if the value is an array or an object, then loop through its values, in order to bring it down to a comparison level. Or you could convert the two data structures to JSON strings with the **JSON.stringify()** function and then compare them.

## A guide using JSON.stringify

The function above works perfectly for shallow objects and this means that the properties in the object should contain a key and a value that is either a string or a number. But if the object property contains a key and a value which is either an array or an object, the function above, won't help out.

Using the function below, you can compare any type of object, as long as you don't need to retrieve its matching properties (content for another day).

The Logic behind the function below is basically just using **JSON.stringify** to convert the object to a JSON string, save the results to a variable, then loop through each character and check if it exists in the other object using the includes method.

I got this suggestion from Sunil and I am happy that it solves the problem.

### Lets Begin

- First, we need to check if the provided variable is an object 
- Then we check if the length of the first object equals the second object

```javascript
function compareObject(obj1, obj2){
  const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
  }
  if(!isObject(obj1) || !isObject(obj2)){
    return false;
  }
  let len = null;
  //check if they're of thesame length
  if(Object.keys(obj1).length != Object.keys(obj2).length){
    return false;
  }else{
    len = JSON.stringify(obj1).length; //use any length
  }
}
```
Next, we will create a *match* variable that will store the number of characters that are matched, and then a *stringified* variable that will store the results of converting the first object to a JSON string using JSON.stringify.

```javascript
function compareObject(obj1, obj2){
  const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
  }
  if(!isObject(obj1) || !isObject(obj2)){
    return false;
  }
  let len = null;
  //check if they're of thesame length
  if(Object.keys(obj1).length != Object.keys(obj2).length){
    return false;
  }else{
    len = JSON.stringify(obj1).length; //use any length
  }
  let match = 0; //store number of matched properties
  let stringified = JSON.stringify(obj1); //use JSON.stringify to convert to JSON string
}
```

Now, we have to loop through the stringified variable and check if each character is contained in the second object stringified. If a match is found, we will increment the match variable, and after the loop, we will check if the match variable equals the length of the stringified object.

The reason I chose to use the includes method and not the comparison operator to check this is because of two equal objects like this;

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645745112545/ntYFqDMOg.png)

Both objects above are equal, but the property value of the second object is an array containing the same values as the first object but in a reverse manner. So if a comparison operator is used to compare this, the result will be false.

That is why I chose to use the includes method to check if the character is included in the second object stringified.

```javascript
function compareObject(obj1, obj2){
  const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
  }
  if(!isObject(obj1) || !isObject(obj2)){
    return false;
  }
  let len = null;
  //check if they're of thesame length
  if(Object.keys(obj1).length != Object.keys(obj2).length){
    return false;
  }else{
    len = JSON.stringify(obj1).length; //use any length
  }
  let match = 0; //store number of matched properties
  let stringified = JSON.stringify(obj1); //use JSON.stringify to convert to JSON string

  let ii = 0;
  //loop through the variable
  while( ii < stringified.length){
    //check if character exists in the other object
    if(JSON.stringify(obj2).includes(stringified[ii])){
      match++; //increment the variable
    }
    ii++;
  }
  //check if object length equals the number of matched properties
  if(match === len){
    return true;
  }
  return false;
}

```

### TESTING

Using our new function, We will start off by comparing the example above, then we will compare an object that contains a complex property (which is the main reason for this post).

#### Comparing the example above

![compare_object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q99sbdrs4wmzoxzaj2qu.png) 

#### Comparing an object with a complex property

```javascript
const obj1 = {
    recipeId : 1,
    count : 1,
    optionGroups : 
    [
        {'og-id' : 1, 'opt-ids' : [7,8,9]},
        {'og-id' : 5, 'opt-ids' : [10,11,12]}
    ]
}
const obj2 = {
    recipeId : 1,
    count : 1,
    optionGroups : 
    [
        {'og-id' : 1, 'opt-ids' : [9,7,8]},
        {'og-id' : 5, 'opt-ids' : [11,10,12]}
    ]
}
const obj3 = {
    recipeId : 1,
    count : 1,
    optionGroups : 
    [
        {'og-id' : 1, 'opt-ids' : [7,8,10]},
        {'og-id' : 5, 'opt-ids' : [10,11,12]}
    ]
}
```

![compare_object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gty6rhd89ztsagmbwgsf.png) 

Looking at the results in the image above, we can say that the objects **obj1 and obj2** are equal!

I hope you have found this useful. Feel free to drop your questions, corrections, or suggestions using the comment box below.

Thank you!