1

I am writing a bunch of unit tests and was wondering what is the best way to compare values of two javascript objects (the actual vs the expected). Lets say I have the following

ActualObject: {
   Val1: '1',
   Val2: '2',
   Val3: '3',
   Val4: '4'
}

ExpectedObject: {
   Val1: '1',
   Val2: '2',
   Val3: '3',
   Val4: '4'
}

Now I want to check if the values of the properties in each of the objects are equal. What is the best way to do this. Currently I am comparing all the properties individually. The alternative I can think of is JSON.stringify, however I'm not sure if this will change the order of the properties at random?

tmp dev
  • 8,043
  • 16
  • 53
  • 108
  • Possible duplicate of [How to determine equality for two JavaScript objects?](https://stackoverflow.com/questions/201183/how-to-determine-equality-for-two-javascript-objects) – Roy G Aug 06 '18 at 07:00

1 Answers1

0

There isn't really a simple "one answer fits all" solution to this, especially as the parameters of your question are quite broad. For example, what would you consider equality? Strict? Loose? Equality of only own enumerable properties, or of all properties?

I would recommend steering clear of using JSON.stringify as 1) it is a fairly costly operation to serialise an object, especially if performing frequently, and 2) it transforms values in potentially dangerous ways for comparison sake (e.g. JSON.stringify(NaN) === JSON.stringify(null) //=> true).

You should use a library implementation such as lodash's isEqual, and save yourself the pain of reinventing the wheel.

However for the sake of completeness, and to give you an idea of a simple, naive approach, you could loop over each property of your object ExpectedObject and check for equality with the equivalent property in the object ActualObject, like so:

function isEqual (ExpectedObject, ActualObject) {
    // if the ExpectedObject has a different number of
    //   keys than ActualObje, it is not equal
    if (Object.keys(ExpectedObject).length !== Object.keys(ActualObject).length) {
        return false
    }

    for (const key in ExpectedObject) {
        // if ActualObject does not have a property that is
        //   on ExpectedObject, it is not equal
        if (!(key in ActualObject)) {
            return false
        }
        // if a property's value on ActualObject is not equal
        //   with a strict comparison, to the equivalent property 
        //   on ExpectedObject, it is not equal
        if (ActualObject[key] !== ExpectedObject[key]) {
            return false
        }
    }

    return true
}

console.log(isEqual({ a:1 }, { a: 1 })) //=> true
console.log(isEqual({ a:1 }, { a: "1" })) //=> false
console.log(isEqual({ a:1 }, { a: 1, b: 2 })) //=> false

Obviously you would need to introduce type-checking so that you know you're dealing with objects to begin with, but there's a basic idea for you to think about.

sdgluck
  • 24,894
  • 8
  • 75
  • 90