Equality Comparisons
Tags: javascript, beginners, webdev, programming
Published: 2023-12-18 19:40:20

In this article, we will break down the 3 ways (operations) to compare values in JavaScript with examples and cover the situations to understand why we even need to compare the values. 

## Value comparison operators
Value comparison operators are an essential part of JavaScript and it’s crucial to understand when and how to use them. By comparing values our main goal is to find out whether it is true or false that these values are equal and only then we can act accordingly. 

We have two main ways to compare values - Loose Equality (“==“) and Strict Equality (“===“). They look very similar so this can lead to confusion. That’s why we will dig deeper to understand the difference. We also have well-known comparison operators like greater than (>), less than (<), greater than or equal to (>=), or less than or equal to (<=).

When we compare the values we simply check if this is equal to that. The result is a boolean value true or false. 

Don’t get confused and use only one equality “=“ like we usually do in mathematics. In the programming world, from the very start, the usage of a single equality was used for assignment and equality as well but due to its ambiguity we now use at least two equal signs (“==“) to use comparison instead of assignment.

## Strict Equality (“===“) 
When we compare two variables by using strict equality, the comparison result depends not only on the value but also on the data type. This type of comparison is more safe, correct and won’t result in bugs. 

Why is it so important? For example, imagine, you are working with a contact form and you have various inputs where one of them was supposed to be saved as a number but is saved as a string. Let’s say, you need to check whether the value received is some specific number so you would use a comparison and check if the value received equals to, for example, 000. Compare the number 000 and the string “000”. 


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpviqba6bp7givcmjphk.png)


Why is the result false? As you can see, the first operand 000 is a number data type while the second one is a string. This means that strict equality checks not only the value but also the data type. If at least one of them is not equal then the final result is not equal.

If we didn’t compare values with strict equality and it returned true, we might have tried to perform some math operations on this string. This would lead to bugs and unexpected results. That’s why it’s important to make sure that we receive not only the correct value but also the data type.

### Numbers, Strings, Booleans, Null & Undefined
The same works for all the data types in JavaScript when it comes to strict equality. 


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3406irjoqtd3h8elkujm.png)


### NaN(Not a Number) 
The NaN never equals even itself because in JavaScript it represents a special kind of “undefined” value. When JavaScript encounters weird operations (for example, 0/0) it returns NaN. Every time you try to compare something to NaN it will always say NO. That’s why, usually to check if the value is a number, we use isNaN() instead.

![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vx66fjktq8l3x9o06rqh.png)


### Arrays
When it comes to arrays and objects in general, things get a little trickier. When the objects are created, their reference is stored in the memory.  After we save this object in a variable, the variable has the information that points to the location of this object in the memory.

Even if we compare two arrays that have the same values inside them, the different variables will hold different places in the memory (have a different reference) which makes them unequal.

In the example below, we compare arrays with each other and themselves. Considering the fact that it’s comparing the reference instead of the actual values inside arrays, we get these results.


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gx1bnfq6mi7mrbav2ms1.png)


In order to compare the values of the arrays and not just the reference, we can create a function that will compare each value one by one.


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5jurqjli7gq6leag80q.png)


### Objects
The same logic of comparison works for any object. Instead of comparing values, JavaScript compares the reference which results in the false value.


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0q4mp1c3fx3iixdcujp.png)


Similar to arrays, we can compare the objects by comparing every key-value pair as a regular comparison isn’t enough. Such comparison is often called deep equality comparison. To check for deep equality, we retrieve the keys of objects and then compare them like in the example below. You can achieve this by using a little different logic as well but this is a short example to illustrate the comparison. 


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgx2x7mxfxbxzu1wdknu.png)


### Functions
In JavaScript, you can even compare functions. If we use a regular comparison operator it will behave the same as it will compare the references. 


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gctlplfg4qwtl9vmg3jo.png)


Instead, we can convert the function reference to a string and compare the equality of strings. However, if both functions have the same body but the names are different, it already makes them unequal.


![Strict Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xes3ioex5zax6gwuzjt7.png)


## Loose Equality (==) 
When comparing two variables by using loose equality, JavaScript attempts to convert the values and compare them that way. That’s why it’s not the best idea to compare variables using this method. If we attempt to compare the number 000 and the string “000”, it will assume that it’s the same.

### Numbers, Strings, Booleans, Null & Undefined
Let’s check what happens when we use loose equality with data types like numbers, strings, null and undefined. 
There are several rules that the loose equality follows:
- strings comparison returns true only when both operands have the same character order. 
- numbers are equal if both have the same value and -0 and +0 are treated as the same. 
- booleans, just like in strict comparison both operands need to be true or false, to return true.


![Loose Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3d828lw81ujom6xdw23m.png)


The comparison of the number 3 with the string 3, returns true this time even though they are different data types.

In the case of undefined and null, however, you will also notice that they are both considered equal. The reason is that JavaScript tries to convert types to the same type when comparing them with loose equality aka type coercion. Only then two values are compared. Due to historical decisions, JavaScript considers both null and undefined equal data types after using type coercion. And one more reason right here why it’s much better to use strict equality.

### NaN(Not a Number) 
NaN never equals NaN or anything else and just like in the previous example, if you want to check whether a value is a number, use the isNaN method.


![Loose Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xyhg89h1fma36rjzmaej.png)


### Arrays, Objects & Functions
With the rest of the data types like objects, we have the same situation as the comparison happens by comparing the references and not the values it contains. 

![Loose Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnsrg4ilsm20za0i543f.png)


![Loose Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6w7j6ar9bhx77gabm9j8.png)


![Loose Equality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z635rbe6tr75jbefqf0r.png)



### Operand conversions
Before comparison, the data types are converted to primitive types as long as they aren’t already the same types. A primitive type is anything besides objects. 

If one of the operands is a type of Symbol and the other is not, it returns false. 

When one of the operands is boolean, the booleans are converted to numbers. True is converted to 1 and false is always converted to 0. This means that if we loosely compared 0 and false, it would return true while true loosely compared to 1 would also return true. 


![Operand conversions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8y4j86dcqszuaycc6t0.png)


When numbers and string are compared, the string is converted to a number. This is exactly why the number 3 and the string 3 were equal. But if the converted thing also fails and ends up being NaN, then it will return false.

Number and BigInt (big integers) are compared by their numeric value as long as the number isn’t +/-infinity or NaN.

Just like with numbers and string, comparing string with BigInt result in the conversion of string to BigInt and return false if this conversion fails. 

## Object.is()
Another way to compare values is a static method Object.is() which accepts two values that we want to compare. Just like loose or strict equality, it returns a boolean value. Note that it is not exactly the same as strict equality or loose equality. However, it is more similar to strict equality than a loose one. It does not do type conversion and doesn’t handle in any special way the NaN, -0, or +0.  This means that Object.is() treats -0 and +0 and NaN as not equal compared to strict equality.


![Object.is()](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wb9osgwdk1098iyyny7.png)


To determine whether Object.is() will return true,  both values should be: 
- undefined
- null
- true or false
- strings of the same length and same character order
- same objects with the same reference
- numbers and both +0, -0, or NaN
- BigInts with same numeric value
- Symbols that refer to the same symbol value


## Equality algorithms
The value comparison operations that we covered earlier correspond to specific equality algorithms in JavaScript. If you are interested in how these operations work in detail, you can check the corresponding abstract operations:

1. Loose equality (“==“) -  [IsLooselyEqual](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal).
2. Strict equality(“===“) - [IsStrictlyEqual](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-isstrictlyequal).
3. Object.is() - [SameValue](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevalue).


## Why do we need equality comparisons?
There are several reasons why we need to compare values. With the help of equality comparisons, we can perform specific actions depending on whether the returned result is true or false. When we know that the comparison will return true or false, we can create a flow of logic on what should happen next. 

Conditional statements like “if”, “else if” or “switch” are great places where we can use the power of equality comparisons. 

In the example below, we check the typeof user input and make sure that it equals to number so we can proceed further. In this case, we use strict equality because it is more trustworthy.


![Why do we need equality comparisons?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uiw9e5cs7qukacgajmc4.png)


Or we can use loose comparison if, for example, the input might be a string and a number and we are fine using both.


![Why do we need equality comparisons?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z285oxd9vvciskilvcrj.png)



It depends on what you are planning to do with the input but in any case, I hope you understand the purpose of the comparison in conditionals. You can do so many variations depending on whether it’s true or false. 


## Conclusion
In conclusion, equality comparisons are vital in JavaScript, offering ways to figure out the equivalence of values. The main tools we use are Loose Equality (==), Strict Equality (===), and Object.is(). Strict Equality ensures both value and data type match, reducing bugs. Loose Equality attempts type conversion, making it less predictable.
Such equality comparisons enable logical flows in conditional statements, allowing us to control code behavior. The choice between strict and loose equality depends on specific situations or preferences.