Equality Comparison of JavaScript Data Types
JavaScript data types
Data types specify what kind of value a variable can have. According to the latest ECMAScript Standard, JavaScript contains eight data types.
They are separated into two categories: primitive and complex.
Primitive data types
- String - characters inside quotations
- Number - integers and floats
- BigInt - integer larger than 253 (largest value for a Number type)
- Boolean - true or false
- Null - non-existing value
- Undefined - declared variable but unassigned value
- Symbols - unique identifiers of objects
Complex data type
Everything else that’s not a primitive data type belongs to a category called Objects.
- Objects - collection of different types of data
Objects (data type) include everything from functions to arrays.
We will focus on objects and arrays.
// object
const book = {
id: 1,
title: 'Red Dragon',
genre: 'Fiction',
};
// array
const library = [
{
id: 1,
title: 'Red Dragon',
genre: 'Fiction',
},
{
id: 2,
title: 'It',
genre: 'Horror',
},
];
Equality comparison
When comparing values, a loose equality comparison (==
) or strict equality comparison (===
) can be used.
Loose equality comparison
If two values are of different data types, they are converted to be the same data type first. After conversion, their values are then compared for equality.
// all comparisons are true
/* no conversion
1 is equal to 1
*/
1 == 1;
/*
1 is converted to '1'
'1' is equal to '1'
*/
1 == '1';
/*
1 is converted into true
true is equal to true
*/
1 == true;
Strict equality comparison
Unlike loose equality comparison, no conversion happens before the values are compared for equality. Therefore, when using ===
data type and values must be equal for it to return true.
1 === 1; // true
/*
false - data type differs
(number vs. string)
*/
1 === '1';
/*
false - data type differs
(number vs. boolean)
*/
1 === true;
Since both ==
and ===
are equality comparisons, which one is preferred?
Stick with ===
because no assumptions are being made about conversions.
As you can see, loose equality (==
) conversions can get quite funky.
Compare primitive data types
We’ve seen a few examples above of comparing primitive types. If the values are equal, comparison returns true. You can also declare variables and compare them.
'red' === 'red'; // true
const color1 = 'red';
const color2 = 'blue';
color1 === 'red'; // true
color1 === color2; // false
When comparing strings, keep in mind that it is case-sensitive.
Each character in the string is compared. Therefore, the strings red
and Red
are not equal.
Compare objects and arrays
Comparing objects and arrays is different from comparing primitive types, such as numbers and strings.
Let’s take a look at the example below.
const color1 = 'red';
const color2 = 'red';
color1 === color2; // true
const colors1 = ['red'];
const colors2 = ['red'];
colors1 === colors2; // false
Why is the first equality comparison true, but the second one false?
Comparison for the primitive data types compares values, whereas non-primitive types (e.g. objects and arrays) compare their references.
Object references
References refer to the location of where the data is stored in the computer’s memory. The arrays colors1
and colors2
occupy two different spaces in memory.
For simplicity’s sake, let’s visualize the computer’s memory as a grid of 5 squares.
1 2 3 4 5
Let’s say at square 1 is the start of colors1
array and at the square 3 is the start of colors2
array. The location 1 and 3 are the arrays’ references.
When comparing arrays, their references are being compared — not the value found at the references.
Therefore, rather than comparing the contents within the array, you’re comparing if 1 is equal to 3. Since 1 doesn’t equal 3, the equality comparison returns false.
Even if you do just [‘red’] === [‘red’], the result is still false because each array occupies a different space in memory.
It helps to think of objects and arrays as houses. They contain a collection of different items, i.e. data, inside.
Even if the two houses are identical on the inside, if one’s address is 123 Maple St. and another is 456 Oak St. they’re still two different houses.
How to actually compare objects and arrays
Two rules for comparing objects and arrays
- They must be the same size (or length)
- All the values inside must be equal
Array
const arr1 = [1, 2, 3, 'abc'];
const arr2 = [1, 2, 3, 'abc'];
arr1 === arr2; // false
function checkArrayEquality(arr1, arr2) {
// first check if the arrays are the same size
if (arr1.length !== arr2.length) {
return false; // equal arrays must be the same size
}
// loop through each element to check if they're equal
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
return false; // each element must be equal
}
}
return true; // after passing all checks the arrays should be equal
}
checkArrayEquality(arr1, arr2); // true
You might have noticed this function doesn’t work if the arrays are sorted differently.
If I do checkArrayEquality([1,2,3], [3,2,1])
it returns false even though I expect it to be true.
In order for this function to work, the arrays must also be sorted. We can add in arr1.sort()
and arr2.sort()
right before the loop to sort the arrays first.
Hurray the function works now! …Except you now need to compare nested arrays.
Would this function still work?
const arr1 = [1, 2, [3, 4]];
const arr2 = [1, 2, [3, 4]];
checkEqualityArray(arr1, arr2); // false
The function returns false. The problems occurs when looping through and comparing each element.
1 === 1; // true
2 === 2; // true
[3, 4] === [3, 4]; // false
When the loop reaches the two arrays, we’re checking if they’re equal to each other. Since the two arrays’ references aren’t the same, [3, 4] === [3, 4]
will return false. The function then stops running.
While it’s possible to write your own function to compare deeply nested objects and arrays, I’d recommend using a library, such as lodash, to compare them. There’s no need to reinvent the wheel, especially when there’s a well-documented and -supported library.
Lodash is a popular library that has an _.isEqual
function to compare objects and arrays. Learn more about Lodash’s isEqual function
Comparing all data types
When comparing any values, first determine if they’re primitive data types or not.
Non-primitive data types, i.e. objects, cannot be compared using equality operator because it compares their references (location in memory). If the objects or arrays are flat and not nested, feel free to write your own helper function to check for equality.
However, if they’re nested, it’ll be easier to use a library. The library will handle checking that every value within the object is equal.
Every other type besides objects can be compared simply with ==
or ===
.