Never again, be stumped by JS Abstract Equality 🤔
Tags: javascript, webdev, codepen, uiweekly
Published: 2021-02-07 12:36:57

>
JavaScript has Strict Equality a.k.a `===` comparison and Abstract Equality a.k.a `==` comparison. It is the latter's lack of understanding which might cause bugs.

---

| Contents |
|-|
| [Rules](#rules) |
| [ToPrimitive, ValueOf, ToString](#toPrimitive-valueof-toString) |
| [Implementing ToPrimitive](#implementingToPrimitive) |

---

###Rules <a name="rules"></a>

![rule](https://media.giphy.com/media/w78T5aWrM7eLatdwDE/giphy.gif)

These are the rules which come into effect while resolving the abstract equality -
1. If `x=null` and `y=undefined`, return `true`;
2. If `x=undefined` and `y=null`, return `true`;
3. If `Type(x)` is same as `Type(y)` then perform strict equality comparison.
4. If `Type(x)=Number` and `Type(y)=String`, return result of `x==ToNumber(y)`
5. If `Type(x)=String` and `Type(y)=Number`, return result of `ToNumber(x)==y`
6. If `Type(x)=Boolean`, return result of `ToNumber(x)==y`
7. If `Type(y)=Boolean`, return result of `x==ToNumber(y)`
8. If `Type(x)` is either `String, Number or Symbol` & `Type(y)` is `Object`, then return result of `x==ToPrimitive(y)`
9. If `Type(y)` is either `String, Number or Symbol` & `Type(x)` is `Object`, then return result of `ToPrimitive(x)==y`

###### Type, ToNumber, ToBoolean are all abstract operations, they are implemented by the JS engine

---

###ToPrimitive, ValueOf, ToString <a name="toPrimitive-valueof-toString"></a>

8th and 9th cases are quite interesting. It involves the conversion of a non-primitive value to a primitive one.

According to the [spec](https://262.ecma-international.org/11.0/#sec-abstract-equality-comparison), the `ToPrimitive` method accepts two arguments - _Input_ and optional _PreferredType_ hint (it could be either `string`, `number` or `default`).

An `object` utilizes the following two methods for conversion if the `ToPrimitive` is not available for the `object` -
1. `valueOf` - takes precedence in case of `number` hint i.e during numerical comparisons, followed by a call to `toString`, if the former does not yield a primitive value

2. `toString` - takes precedence in case of `string` hint, followed by a call to `valueOf`, if the former does not yield a primitive value

For the `default` hint case, it's considered as `number` unless the `object` is of `Date` type.

Enough talking, let's see code in action for the above statements

{% replit @sagarrth/Abstract-Equality-and-Coercion %}

---

###Implementing ToPrimitive <a name="implementingToPrimitive"></a>

`Symbol.toPrimitive` is the way to implement an `object`'s `toPrimitive` operation. If this method does not return a primitive, then an error is thrown. The snippet below shows how one could implement any custom logic for object coercion.

{% replit @sagarrth/Implementing-ToPrimitive %}

---

Reference: 
- [ECMAScript spec 7.1.1](https://262.ecma-international.org/11.0/#sec-toprimitive)
- [ECMAScript spec 7.2.15](https://262.ecma-international.org/11.0/#sec-abstract-equality-comparison)
- [ECMAScript spec 6.1.5.1](https://262.ecma-international.org/11.0/#sec-well-known-symbols)

That's all people!

![thankyou](https://media.giphy.com/media/26gsjCZpPolPr3sBy/giphy.gif)