Thought leadership from the most innovative tech companies, all in one place.

Comparing Objects in JavaScript

What works, what doesn't and why

Photo courtesy of theubercloud.com

It’s easy to compare objects for equality, but not so easy to tell if they contain the same keys and values. But Why? My goal is to explain why determining if two objects contain the same values can be difficult.

Why explain a problem. Just give me the solution?

Because understanding what is difficult or does not work, can give us a deeper understanding of why and often lead us to look for, or develop solutions, that will work. A link to a great video is at the end of this story.

Primitive data types versus Reference (non-primitive) types

Essentially it has to do with JavaScript primitives versus JavaScript non-primitives (objects).

As I will demonstrate, through code and analogy, variables containing a primitive type are given a **value **in memory. Variables containing a non-primitive type are given a **reference **in memory.

Primitive type and memory allocation

Example 1

The primitive types, keeping it simple, are number, string, boolean, undefined and null. A full list can be found here.

Primitives have a value in memoryPrimitives have a value in memory

What’s happening? For any primitive, memory is allocated and the value of the primitive is stored in that memory location.

To borrow a common analogy, lets say I write the number 1 on a sticky note and put it on the white board. It is to remind myself that I have one task today. (Of course I could write the task but let’s keep it simple.)

My office partner writes the number 1 on a sticky note to remind himself what time he has a meeting and puts it on the white board as well.

The sticky notes are different and each contain their own value.

Think of each sticky note as memory allocated and the number as the value stored in the allocated memory. When compared, in this case, they contain the same value, 1.

When we compare primitives, we compare the values stored in the memory locations.

If I get a new task and change my sticky note to 2, then it does not affect the other sticky note. They each have their own value.

Example 2

Each has their own memory allocationEach has their own memory allocation

The variable, a, was allocated memory and given the value of 1. Variable b was given it’s own memory space and given the value of the variable a, 1. It does not point to a, it is independent of a, and contains it’s own value.

So when the variable a is changed, the variable b remains the same.

In JavaScript, every primitive gets it’s own memory space when declared. When assigned a value, that value goes into the memory space.

Reference type and memory allocation

Reference types, to keep it simple, are Objects, Functions and Arrays, collectively known as objects. More information can be found here.

Example 3

The variables obj1 and obj2 contain a reference. Each to a separate memory location.The variables obj1 and obj2 contain a reference. Each to a separate memory location.

The important thing to understand here is that the variables, obj1 and obj2 (which could be an Object, Array or Function) each contain only a reference to a location in memory. Not the value of the object.

The locations are separate, so the references are different, and the comparison fails. We are not comparing the values of the objects, but the references to their memory locations.

So for JavaScript reference types, we get allocations in memory when the object is declared, but the variable only gets a reference to the objects location in memory, not it’s value.

Back to our sticky note analogy.

If I decide to create a list of tasks (not primitive) and place it on my desk, the sticky note on the white board contains information telling me where to look for the list, not the list itself.

The sticky note contains a message like “look on the desk, bottom left corner.”

If I decide to create a second task list, and put that on my desk, another sticky is placed on the white board telling me where to look for the second list, “look on the desk, bottom right corner.)

If I compare the sticky note messages on the white board, they are not equal.

So even if task list 2 is the same as task list 1 (same or different order) the references are different and they will not be equal.

Assigning Reference Types

If you recall in Example 2, we assigned a primitive to the variable a. We then assigned to the variable b the value in the variable a.

Because each had their it’s memory space, changing the value of the variable, a, did not change the value of the variable, b.

With reference types it is different.

Example 4

Both variables contain the same information, a reference to the object’s location.Both variables contain the same information, a reference to the object’s location.

In this case they are equal, because the variables contain the same information, the same reference to the object’s location in memory.

In the sticky note analogy, it is as if I had two sticky notes on the white board telling me where to find the original list (on the desk, bottom left corner.) They contain the same information, so are equal.

Example 5

Changing the value of either obj1 or obj2 changes the other since they both point to the same object. (Compare to Example 2.)

They both have the same reference to the same object.They both have the same reference to the same object.

How do we compare objects?

Comparing objects is easy, use === or Object.is(). This function returns true if they have the same reference and false if they do not.

Again, let me stress, it is comparing the references to the objects, not the keys and values of the objects.

So, from Example 3, Object.is(obj1,obj2); would return false. In Example 4, Object.is(obj1,obj2); would return true.

So even if two objects contain the same data, === and Object.is() will return false, unless the variables contain a reference to the same object.

Comparing object keys and values is more complex.

Possibly Simple Solution

One possible simple solution is to JSON.stringify the objects and then compare the strings. This works fine if the keys are in the same order. This cannot be guaranteed however. In addition, you are comparing strings, not objects.

Another Idea

One step in the right direction is to use Object.keys() and Object.values(). Or Object.entries().

Conclusion

So we have seen that comparing two objects is more than just looking at the variables. These variables only contain references.

Determining if they contain the same values can be a complex process.

I highly recommend this youtube video on programmatically determining if two object values equal each other.

JS Tutorial: Find if Two Object Values are Equal to Each Other

as well as look in to the following npm package. Lodash’s, _.isEqual().

Thanks for reading and happy coding!




Continue Learning