ПІДТРИМАЙ УКРАЇНУ ПІДТРИМАТИ АРМІЮ
Uk Uk

Why are two similar objects not equal in JavaScript?

Why are two similar objects not equal in JavaScript?

JavaScript compare two objects. Why is that case two objects not equal even though they are similar?

In JavaScript, two objects cannot be equal even though they are similar. Why is that the case? ???? Let's understand why.

For example:

const obj1 = {
 name: "Dillion"
}
const obj2 = {
 name: "Dillion"
}

console.log(obj1 === obj2)
// false

As you can see here,obj1andobj2look similar; they both have the property ofnamewith a value of "Dillion". But comparing them--obj1 === obj2--returnsfalse????

The same thing applies to arrays:

let arr1 = [1, 2, 3]
let arr2 = [1, 2, 3]

console.log(arr1 === arr2)
// false

To understand why this is the case, you have to understand what primitive and reference values are in JavaSCript.

Primitive and Reference Values

Think of a primitive value as one value(static, fixed) and a reference value as a group of multiple values or (dynamic) value.

Primitive values are of the typesstring,number,boolean,null,undefined,symbol, andBigInt. These values are fixed and stored on the stack, for example:

let name = "Dillion"
let age = 60
let isRaining = true

image-71

Reference values are of theobjecttypes which includes objects, arrays and functions. These values are dynamic (can contain multiple values, properties, and can be modified over time) and are stored on the heap, with a reference value in the stack, for example:

let array = [1, 2, 3]
let obj = { name: "Dillion" }
function print() {
 console.log('hello')
}

image-72

The reference value is an address that points to the location of the data in the memory.

Here's an article where I explained the difference in more detail: Primitive and Reference Values Simplified 

Comparing Primitive and Reference Values

When you compare primitive values, you are comparing static values, which have a fixed size on the stack:

let name = "Dillion"
let name2 = "Dillion"

console.log(name === name2)
// true

Here, we comparenameandname2if they are equal. What happens here is that JavaScript checks for thenameandname2variables in the stack, and then it sees that they have equal values, so it's true--they are equal.

In the case of objects, you are comparing the references(the addresses) and not the exact values. Here's what I mean.

If you have two arrays like this:

let array = [1, 2, 3]
let array2 = [1, 2, 3]

Here's what it would look like on the stack and heap:

image-73

As you can see here, forarray,[1, 2, 3]is not stored on the stack. It is stored on the heap, and the memory location of that data is stored on the stack as a reference.

The same thing forarray2;[1, 2, 3]is not stored on the stack. It is stored on the heap, in a different memory location and the reference is stored on the stack.

When you compare both arrays likearray === array2, you're not exactly comparing[1, 2, 3] === [1, 2, 3]but you're actually comparingrefForArray === refForArray2(ref is short for reference).

As we saw in the heap illustration,arrayandarray2have different memory locations, which means they have different references, which then means the variablearrayis not equal to the variablearray2.

The only wayarrayandarray2can be equal, is if you have something like:

let array = [1, 2, 3]
let array2 = array

console.log(array === array2)
// true

By assigningarraytoarray2, you are assigning the reference thatarrayholds in the stack, toarray2:

image-74

Therefore,arrayandarray2now have the same value-the same reference.

How to compare objects

We've seen that in our attempt to compare two object values, we are actually comparing the reference and not the object data. So how do we correctly compare the object data?

There are a couple of ways you can do this but I will share two of them.

Compare objects using_.isEqual from Lodash

You can write a function that does an equality check between two objects, but it could become complicated when you have to compare deeply nested objects which can have different values, including objects.

A faster approach is using the isEqual method from Lodash which is an effective solution that handles deep comparison between two values:

const _ = require('lodash'); 

const array = [1, 2, 3]
const object = { name: "Dillion" }

const array2 = [1, 2, 3]
const object2 = { name: "Dillion" }

console.log(_.isEqual(array, array2))
// true

console.log(_.isEqual(object, object2))
/ true

Compare objects usingJSON.stringify()

Say you don't want to use Lodash, you can useJSON.stringifywhich recursively stringifies an object or array to a string:

const array = [1, 2, 3]
const object = { name: "Dillion" }

const array2 = [1, 2, 3]
const object2 = { name: "Dillion" }

console.log(
 JSON.stringify(array)
 ===
 JSON.stringify(array2)
)
// true

console.log(
 JSON.stringify(object)
 ===
 JSON.stringify(object2)
)
// true

Since the stringified version is a primitive type (static), the data of both values can be compared. But here is a limitation withJSON.stringify().

JSON.stringifycan return different results if the order or properties in an object are different. For example:

const object = {
 name: "Dillion",
 age: 50
}

const object2 = {
 age: 50,
 name: "Dillion"
}

console.log(
 JSON.stringify(object)
 ===
 JSON.stringify(object2)
)
// false

Inobject, we havenamecoming beforeage, but inobject2, we haveagecoming beforename. This means their stringified representations would be different and as a result, their data are not equal.

Wrap up

Primitive and Reference values are fundamental concepts to understand when working with data in JavaScript. And as we have seen in this article, comparing primitive values is easier, but comparing reference values can be trickier because when you think you are comparing the data, you may not realize that you are actually comparing the reference.

Ресурс : freecodecamp.org


Scroll to Top