This is the second post in my Javascript serial.

There are 3 types of comparison operators in Javascript

`===`

(most recommend): strict comparison or identity comparison`==`

(not recommend): loose comparison`Object.is`

api: SameValue comparison. Added from ES6.

From my practical experience, `===`

is the first comparison you should consider when choosing one from above three types, as it works in every version of Javascript implementation.

`==`

is indeed discouraged in default ESlint configuration.

`Object.is`

is added from ES6. You should check compatibility and apply polyfill if your client's browser does not support.

## What is the difference?

Because `==`

is not so useful and it will raise my eslint warning when being used. I have never used or seen any use case of the loose comparison `==`

operator in real life. Thus, I will not discuss about the loose comparison operator here.

The main difference between `===`

and `Object.is`

is how do they handle these 3 special primitive number values: `+0`

, `-0`

, and `NaN`

.

`+0`

and `-0`

have same mathematical semantic meaning and they are same in most of mathematical operations. However, in fact, they are different values and have different byte presentations.

With strict comparison `===`

, `+0`

equals to `-0`

, in vice versa, `NaN`

is not equal to itself ( `0`

is interpreted as `+0`

). While these comparisons' result are both reversed with `Object.is`

comparison. Check ECMS ( strict equality, SameValue ) specification for reference.

## Why +0, -0 and NaN?

To understand this specification, you should have a look at double-precision binary floating-point format binary64. It is not required you to read the reference to understand my following content in this paragraph.

In Javascript, the fact that number is stored in IEEE754 format ( ref) implies that all numbers in Javascript have theirs own 64 bit (i.e. 8 bytes) presentations.

However, this does not mean that all 64 bit binary arrays have its own float value due to the specification of IEEE754 format. In other words, the map from IEEE754 formatted number (or Javascript number) to 64-bit binary array is injective but not surjective.

Thus, there are many 64-bit binary arrays do not have equivalent number value. In Javascript, 2 of them are chosen to be `Infinity`

and `-Infinity`

. All other non-associated values are consider not-a-number ( `NaN`

) instances. Thus, there is not only one but many `NaN`

instance.

I could not found whether ECMA specification defines these special number values' binary presentation from the specs. Thus, I consider the binary presentation varies from implementation to implementation.

Use this script from MDN docs to check for binary presentation of an arbitrary number.

```
var f2b = x => new Uint8Array(new Float64Array([x]).buffer);
var b2f = x => new Float64Array(x.buffer)[0];
```

`f2b`

converts number value to 8-length byte array, `b2f`

converts `Unit8Array`

instance to a number. Using `f2b`

, we can check for default `NaN`

instance, `Infinity`

and `-Infinity`

binary representations.

```
f2b(NaN) //Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
f2b(Infinity) //Uint8Array(8) [0, 0, 0, 0, 0, 0, 240, 127]
f2b(+Infinity) //Uint8Array(8) [0, 0, 0, 0, 0, 0, 240, 127]
f2b(-Infinity) //Uint8Array(8) [0, 0, 0, 0, 0, 0, 240, 255]
f2b(0) //[0, 0, 0, 0, 0, 0, 0, 0]
f2b(+0) //[0, 0, 0, 0, 0, 0, 0, 0]
f2b(-0) //[0, 0, 0, 0, 0, 0, 0, 128]
```

Though out above discussion, we understand that in Javascript, the strict equal `===`

operators give understandable and common sense operation. `===`

considers all values are different from `NaN`

even the `NaN`

itself. And the only case in which `x !== x`

is `true`

is when `x`

is `NaN`

, in a sense that we do not know which instance the `NaN`

value is.

There are 2 ways to check if a value is `NaN`

in Javascript. Via `Object.is(NaN, x)`

or `isNaN(x)`

.

## Quirk

Check these expressions' result from your browser. This quirk requires your browser to support ES6 Array.prototype.includes().

```
let x = 'hello'
[x].includes(x) // true
[x].indexOf(x) // 0
x = NaN
[x].includes(x) // true
[x].indexOf(x) // -1
```

The result can be explained by the fact that `.includes()`

use `Object.is`

comparison, in the contrast of strict equal `===`

comparison used by `.indexOf()`

.

Bonus image from a MDN article

In this post, I have shared my knowledge about equality comparison operators in Javascript. Mostly I discussed about the strict comparison and SameValue comparison.

Please feel free to discuss.