Logo

dev-resources.site

for different kinds of informations.

Compare Anything in JavaScript with Just A Function

Published at
7/7/2022
Categories
javascript
algorithms
compare
webdev
Author
rasaf_ibrahim
Author
13 person written this
rasaf_ibrahim
open
Compare Anything in JavaScript with Just A Function

✅ In this article, we will create a function that can compare not only strings, numbers, and booleans but also arrays and objects. The arrays and objects that this function will compare can have nested arrays, and nested objects. Also, the objects can not only have enumerable properties but also nonenumerable. If you want to see a preview, go to the last section: Preview

 

🔖 Table of Contents

 

Step 1: Creating the function

 

Let's name this function compareAnything and this function will accept two arguments: first & second.

function compareAnything (first, second) {

 ...

}
Enter fullscreen mode Exit fullscreen mode

We can pass two values as arguments. This function will return a boolean value after comparing those values.

 

Step 2: Checking Null

 

In this step, we will check whether any of the arguments is null. If any argument is null, we have nothing to compare, we will simply return false. But if none of them are null, we will move forward to the next step.

function compareAnything (first, second) {

   if(first === null || second === null) return false

}

Enter fullscreen mode Exit fullscreen mode

 

Step 3: Checking String and Number and Boolean

 

It's easy to compare strings, numbers, and booleans. We just need to use a strict equality operator (===).

function compareAnything (first, second) {

    ...

    /* Using the strict equality operator (===) */
    if(first === second) return true

}

Enter fullscreen mode Exit fullscreen mode

If the arguments are equal, we are returning true. But if they are not equal, then surely they are not strings or numbers or booleans. Maybe they are objects or arrays. So, we will move forward to the next step.

 

⚠️

Important Info

 

 

Why it's a little bit tough to compare two objects

 

Before going to step 4, let's understand why it's tough to compare two objects. In JavaScript, objects are stored by reference. That means one object is strictly equal to another only if they both point to the same object in memory.

This GIF is collected from panjee.com and modified afterward.

 

const obj_1 = { score: 12 }
const obj_2 = obj_1
const obj_3 = { score: 12 }

obj_1 === obj_2; // true, same reference
obj_1 === obj_3 // false, different reference but same keys and values
Enter fullscreen mode Exit fullscreen mode

 

Arrays are objects

 

Arrays are a special type of object. The typeof operator in JavaScript returns "object" for arrays.

let a = [1, 2, 3]
console.log(typeof a) // object
Enter fullscreen mode Exit fullscreen mode

So, from now we will only focus on comparing two objects. If we can make functionality to compare two objects, that functionality will also compare two arrays automatically.

 

Step 4: Checking Type

 

In this step, we will make sure that the type of the argument is object. If any of the arguments is not an object, we will return false.

function compareAnything (first, second) {

    ...

   if(typeof first !== 'object'  || typeof second !== 'object') return false

}

Enter fullscreen mode Exit fullscreen mode

Note:

The typeof operator in JavaScript returns "object" for arrays too. So, in this step, we are checking for both arrays and objects.

 

Step 5: Checking the total number of properties

 

In the last step, we have made sure that both arguments are objects. In this step, we will check whether both objects have the same number of properties or not. If they don't have the same number of properties, we will return false.

function compareAnything (first, second) {

    ...

   /* Using Object.getOwnPropertyNames() method to return the list of the objects’ properties*/
 let first_keys = Object.getOwnPropertyNames(first)

 let second_keys = Object.getOwnPropertyNames(second)


  /* Using array.length() method to count the number of total property */
  if(first_keys.length !== second_keys.length) return false

}

Enter fullscreen mode Exit fullscreen mode

Could we use Object.keys() instead of Object.getOwnPropertyNames()?

No. Because Object.keys() can't return Nonenumerable
property's name but Object.getOwnPropertyNames() can.

 

Step 6: Checking Property Names

 

In the last step, we made sure that both objects have the same number of properties. Now, we need to make sure that the properties' names of both objects are the same. If they are not the same, we will return false. But if they are the same, we will move forward to the next step.

function compareAnything (first, second) {

    ...


  /* Iterating through all the properties of the first object with for..of method */
 for(let key of first_keys) {


    /* Making sure that every property in the first object also exists in the second object */ 
    if(!Object.hasOwn(second, key)) return false


 }


}

Enter fullscreen mode Exit fullscreen mode

Could we use Object.hasOwnProperty() instead of Object.hasOwn()?

No. Because Object.hasOwnProperty() can't check a Nonenumerable property's name but Object.hasOwnProperty() can. Also, Object.hasOwn() is intended as a replacement for Object.hasOwnProperty(), so we are using Object.hasOwn() here.

 

Step 7: Checking Property Values

 

In the last step, we made sure that the property names of both objects are the same. Now, we will check whether the property values of both objects are the same or not.

 

This step is a little bit tricky because:

 

  • The property values can not only be strings, numbers, or boolean but also nested objects.
  • Just checking with strict equality operator (===) would be enough if the values were string or number or boolean but it wouldn't be enough for an object because the nested object will have its own properties.
  • Let's suppose that the nested object has another object inside it as a property! What will we do? Will we check one by one!

 

Solution:

 

  • In the step 1, we created this compareAnything function, and this function not only checks the strict equality operator (===), but also it checks null or not, object or not, properties of objects are the same or not. So, actually, we need a function like this compareAnything to check any nested object's properties.
  • Fortunately, we don't need to create any new function because there is a term known as the recursive function. A recursive function is a function that calls itself during its execution. So, we can use this compareAnything function as a recursive function.

Now, let's use this compareAnything function to check whether the property values of both objects are the same or not. If they are not the same, we will return false.

function compareAnything (first, second) {

    ...



 for(let key of first_keys) {



     ...


   /* Using the compareAnything function recursively and passing the values of each property into it to check if they are equal. */

  if (compareAnything(first[key], second[key]) === false) return false



}

Enter fullscreen mode Exit fullscreen mode

Note

As the compareAnything is inside a loop. So, it will continue to execute itself till it finishes checking all the nested objects.

 

Step 8: The Last Step

 

If we are in this step 8, that means no other step's condition matched. As we have checked almost all possible ways in which the objects are not the same and none of those conditions matched, so now we can surely say that the objects are the same. So, we will simply return true in this step.

function compareAnything (first, second) {

    ...


  for(let key of first_keys) {



     ...


   }

 return true

}

Enter fullscreen mode Exit fullscreen mode

 

Full Code

 

function compareAnything (first, second) {


  /* Checking if any arguments are null */
  if(first === null || second === null) return false


  /* Checking if the types and values of the two arguments are the same. */
  if(first === second) return true


  /* Checking if any argument is none object */
  if(typeof first !== 'object'  || typeof second !== 'object') return false


  /* Using Object.getOwnPropertyNames() method to return the list of the objects’ properties */
  let first_keys = Object.getOwnPropertyNames(first)

  let second_keys = Object.getOwnPropertyNames(second)



  /* Checking if the objects' length are same*/
  if(first_keys.length !== second_keys.length) return false




  /* Iterating through all the properties of the first object with the for of method*/
  for(let key of first_keys) {


      /* Making sure that every property in the first object also exists in second object. */ 
      if(!Object.hasOwn(second, key)) return false


      /* Using the compareAnything function recursively (calling itself) and passing the values of each property into it to check if they are equal. */
      if (compareAnything(first[key], second[key]) === false) return false

  }



  /* if no case matches, returning true */ 
  return true


}


Enter fullscreen mode Exit fullscreen mode

 

Testing

 

 

String

 

const string_1 = 'rasaf'
const string_2 = 'ibrahim'
const string_3 = 'rasaf'

console.log(compareAnything(string_1, string_2)) //false
console.log(compareAnything(string_1, string_3)) // true
console.log(compareAnything(string_2, string_3)) // false
Enter fullscreen mode Exit fullscreen mode

 

Number

 

const number_1 = 100
const number_2 = 200
const number_3 = 100

console.log(compareAnything(number_1, number_2)) //false
console.log(compareAnything(number_1, number_3)) // true
console.log(compareAnything(number_2, number_3)) // false

Enter fullscreen mode Exit fullscreen mode

 

Boolean

 

const boolean_1 = true
const boolean_2 = false
const boolean_3 = true

console.log(compareAnything(boolean_1, boolean_2)) //false
console.log(compareAnything(boolean_1, boolean_3)) // true
console.log(compareAnything(boolean_2, boolean_3)) // false
Enter fullscreen mode Exit fullscreen mode

 

Array

 

let arr_1 = [
  {
    color: 'red',
    type: 'station wagon',
    registration: 'Sat Mar 03 2018 01:00:00 GMT+0100 (GMT+01:00)',
    capacity: 5
  },
  {
    color: 'red',
    type: 'cabrio',
    registration: 'Sat Mar 03 2012 01:00:00 GMT+0100 (GMT+01:00)',
    capacity: 2
  }
]


let arr_2 = [
  {
    color: 'red',
    type: 'station wagon',
    registration: 'Sat Mar 03 2018 01:00:00 GMT+0100 (GMT+01:00)',
    capacity: 5
  },
  {
    color: 'red',
    type: 'cabrio',
    registration: 'Sat Mar 03 2012 01:00:00 GMT+0100 (GMT+01:00)',
    capacity: 2
  }
]

console.log(compareAnything(arr_1, arr_2)) //true
Enter fullscreen mode Exit fullscreen mode

 

Object

 

let obj_1 = {
  name: "Rasaf",
  additionalData: {
      favoriteHobbies: ["Playing Cricket", "Watching Movies"],
      citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
      }
  }


let obj_2 = {
  name: "Rasaf",
  additionalData: {
      favoriteHobbies: ["Playing Football", "Watching Movies"],
      citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
      }
  }


let obj_3 = {
  name: "Rasaf",
  additionalData: {
      favoriteHobbies: ["Playing Cricket", "Watching Movies"],
      citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
      }
  }

console.log(compareAnything(obj_1, obj_2)) //false
console.log(compareAnything(obj_1, obj_3)) // true
console.log(compareAnything(obj_2, obj_3)) // false
Enter fullscreen mode Exit fullscreen mode

 

Object (Enumerable & Nonenumerable Properties)

 

let obj_1 = {
  name: "Rasaf",
  additionalData: {
      favoriteHobbies: ["Playing Cricket", "Watching Movies"],
      citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
      }
  }


  let obj_2 = {
    name: "Rasaf",
    additionalData: {
        favoriteHobbies: ["Playing Cricket", "Watching Movies"],
        citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
        }
    }


let obj_3 = {
  name: "Rasaf",
  additionalData: {
      favoriteHobbies: ["Playing Football", "Watching Movies"],
      citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
      }
  }
  Object.defineProperty(obj_3, 'noneEnumble', {
    value: 123,
    enumerable: false
  });


  let obj_4 = {
    name: "Rasaf",
    additionalData: {
        favoriteHobbies: ["Playing Football", "Watching Movies"],
        citiesLivedIn: ["Rajshahi", "Rangpur", "Joypurhat"]
        }
    }
    Object.defineProperty(obj_4, 'noneEnumble', {
      value: 123,
      enumerable: false
    });




console.log(compareAnything(obj_1, obj_2)) //true
console.log(compareAnything(obj_1, obj_3)) // false
console.log(compareAnything(obj_2, obj_3)) // false
console.log(compareAnything(obj_3, obj_4)) // true

Enter fullscreen mode Exit fullscreen mode

That's it. 😃 Thanks for reading. 🎉 If you find any typos or errors, or if you want to add something, please write it down in the comment section.

compare Article's
25 articles in total
Favicon
mismatch() and compare() in Java
Favicon
Vector Library versus Vector Database
Favicon
Top Reasons to Compare and Switch Electricity Providers
Favicon
Webcare360 vs QloudHost: Deep Dive into Two Leading DMCA Ignored Hosting Providers
Favicon
Astro vs Visual Studio 2022 as Static Site Generators
Favicon
Java VS .NET: Which one is better
Favicon
How to Compare Same Contents but Different Ordered Arrays in JavaScript?
Favicon
PDF-Verwaltung: Vergleich von PDF-Dokumenten mit Java, um Unterschiede im Inhalt zu finden
Favicon
Compare Colors Palettes
Favicon
Alternative libs to migrate from React to Vue (or Vue to React)
Favicon
Compare Anything in JavaScript with Just A Function
Favicon
Java - How to Compare Two Word Documents to Get Differences
Favicon
A Command-line tool to statistics the GitHub repositories
Favicon
Kotlin – Compare Objects with Comparable Example
Favicon
Digital Ocean App Platform vs Heroku
Favicon
42% the Size of HTML SCSS with ZIM...
Favicon
Compare Two Word documents and get the difference reports in Java
Favicon
Rust vs Go in Backend Web Development
Favicon
List of Cloud Products (opt, cont. update)*
Favicon
Mocking in Elixir: Comparison between Mox, Mockery, Mimic, Syringe, and Lightweight DI
Favicon
CodePen vs CodeSandbox - JavaScript playgrounds compared
Favicon
CodeTip - Javascript: Compare class instances
Favicon
Azure vs GCP part 2: Compare Web Apps and App Engine service
Favicon
Recommend: Five Language Stories
Favicon
CodeTip - Ruby: Compare class instances

Featured ones: