Compare Things In JavaScript [Explained in A Gross Amount of Detail]
Tags: javascript, coding, testing, node
Published: 2021-08-08 04:37:16

{% user cleancodestudio %}
[![Twitter Follow](https://img.shields.io/twitter/follow/cleancodestudio.svg?style=social)](https://twitter.com/cleancodestudio) 

---

<center>
Ever get stuck wondering if you need...
</center>

<center>
```js
a == b
```
or 
```js
a === b
```

or 

```js
isLooselyEqual(a, b)
```

or 

```js
isStrictlyEqual(a, b)
```



</center>

---

<center>
I know I sure have.
</center>


---

> _Testing and Comparison Operations - the actual definitions._

> _This is content pulled directly from [ECMAscript specifications](https://tc39.es/ecma262/)(Not written by me). It defines specifically how comparisons/testing operations work to an almost grows amount of detail. Good reference to have if you're unsure whether you need two equal signs or one equal sign to check if two things are the same or different._ 


---

## 7.2.2 IsArray ( argument )

---

The abstract operation IsArray takes argument argument. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is not Object, return false.
2.  2\. If argument is an [Array exotic object](https://tc39.es/ecma262/#array-exotic-object), return true.
3.  3\. If argument is a [Proxy exotic object](https://tc39.es/ecma262/#proxy-exotic-object), then
    1.  a. If argument.\[\[ProxyHandler\]\] is null, throw a TypeError exception.
    2.  b. Let target be argument.\[\[ProxyTarget\]\].
    3.  c. Return ? [IsArray](https://tc39.es/ecma262/#sec-isarray)(target).
4.  4\. Return false.

---

## 7.2.3 IsCallable ( argument )

---

The abstract operation IsCallable takes argument argument (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It determines if argument is a callable function with a \[\[Call\]\] internal method. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is not Object, return false.
2.  2\. If argument has a \[\[Call\]\] internal method, return true.
3.  3\. Return false.

---

## 7.2.4 IsConstructor ( argument )

---

The abstract operation IsConstructor takes argument argument (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It determines if argument is a [function object](https://tc39.es/ecma262/#function-object) with a \[\[Construct\]\] internal method. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is not Object, return false.
2.  2\. If argument has a \[\[Construct\]\] internal method, return true.
3.  3\. Return false.

---

## 7.2.5 IsExtensible ( O )

---

The abstract operation IsExtensible takes argument O (an Object). It returns a completion record which, if its \[\[Type\]\] is normal, has a \[\[Value\]\] which is a Boolean. It is used to determine whether additional properties can be added to O. It performs the following steps when called:

1.  1\. [Assert](https://tc39.es/ecma262/#assert): [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(O) is Object.
2.  2\. Return ? O.\[\[IsExtensible\]\]().

---

## 7.2.6 IsIntegralNumber ( argument )

---

The abstract operation IsIntegralNumber takes argument argument. It determines if argument is a finite [integral Number](https://tc39.es/ecma262/#integral-number) value. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is not Number, return false.
2.  2\. If argument is NaN, +∞𝔽, or \-∞𝔽, return false.
3.  3\. If [floor](https://tc39.es/ecma262/#eqn-floor)([abs](https://tc39.es/ecma262/#eqn-abs)([ℝ](https://tc39.es/ecma262/#ℝ)(argument))) ≠ [abs](https://tc39.es/ecma262/#eqn-abs)([ℝ](https://tc39.es/ecma262/#ℝ)(argument)), return false.
4.  4\. Return true.

---

## 7.2.7 IsPropertyKey ( argument )

---

The abstract operation IsPropertyKey takes argument argument (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It determines if argument is a value that may be used as a property key. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is String, return true.
2.  2\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is Symbol, return true.
3.  3\. Return false.

---

## 7.2.8 IsRegExp ( argument )

---

The abstract operation IsRegExp takes argument argument. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(argument) is not Object, return false.
2.  2\. Let matcher be ? [Get](https://tc39.es/ecma262/#sec-get-o-p)(argument, [@@match](https://tc39.es/ecma262/#sec-well-known-symbols)).
3.  3\. If matcher is not undefined, return ! [ToBoolean](https://tc39.es/ecma262/#sec-toboolean)(matcher).
4.  4\. If argument has a \[\[RegExpMatcher\]\] internal slot, return true.
5.  5\. Return false.

---

## 7.2.9 IsStringPrefix ( p, q )

---

The abstract operation IsStringPrefix takes arguments p (a String) and q (a String). It determines if p is a prefix of q. It performs the following steps when called:

1.  1\. [Assert](https://tc39.es/ecma262/#assert): [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(p) is String.
2.  2\. [Assert](https://tc39.es/ecma262/#assert): [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(q) is String.
3.  3\. If q can be the [string-concatenation](https://tc39.es/ecma262/#string-concatenation) of p and some other String r, return true. Otherwise, return false.

```
Note

Any String is a prefix of itself, because r may be the empty String.
```

---

## 7.2.10 SameValue ( x, y )

---

The abstract operation SameValue takes arguments x (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)) and y (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It returns a completion record whose \[\[Type\]\] is normal and whose \[\[Value\]\] is a Boolean. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is different from [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y), return false.
2.  2\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Number or BigInt, then
    1.  a. Return ! [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x)::sameValue(x, y).
3.  3\. Return ! [SameValueNonNumeric](https://tc39.es/ecma262/#sec-samevaluenonnumeric)(x, y).

```
Note

This algorithm differs from the [IsStrictlyEqual](https://tc39.es/ecma262/#sec-isstrictlyequal) Algorithm in its treatment of signed zeroes and NaNs.
```

---

## 7.2.11 SameValueZero ( x, y )

---

The abstract operation SameValueZero takes arguments x (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)) and y (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It returns a completion record whose \[\[Type\]\] is normal and whose \[\[Value\]\] is a Boolean. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is different from [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y), return false.
2.  2\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Number or BigInt, then
    1.  a. Return ! [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x)::sameValueZero(x, y).
3.  3\. Return ! [SameValueNonNumeric](https://tc39.es/ecma262/#sec-samevaluenonnumeric)(x, y).

```
Note

SameValueZero differs from [SameValue](https://tc39.es/ecma262/#sec-samevalue) only in its treatment of +0𝔽 and \-0𝔽.
```

---

## 7.2.12 SameValueNonNumeric ( x, y )

---

The abstract operation SameValueNonNumeric takes arguments x (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)) and y (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It returns a completion record whose \[\[Type\]\] is normal and whose \[\[Value\]\] is a Boolean. It performs the following steps when called:

1.  1\. [Assert](https://tc39.es/ecma262/#assert): [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is not Number or BigInt.
2.  2\. [Assert](https://tc39.es/ecma262/#assert): [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is the same as [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y).
3.  3\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Undefined, return true.
4.  4\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Null, return true.
5.  5\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is String, then
    1.  a. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
6.  6\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Boolean, then
    1.  a. If x and y are both true or both false, return true; otherwise, return false.
7.  7\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Symbol, then
    1.  a. If x and y are both the same Symbol value, return true; otherwise, return false.
8.  8\. If x and y are the same Object value, return true. Otherwise, return false.

---

## 7.2.13 IsLessThan ( x, y, LeftFirst )

---

The abstract operation IsLessThan takes arguments x (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)), y (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)), and LeftFirst (a Boolean). It provides the semantics for the comparison x < y, returning true, false, or undefined (which indicates that at least one operand is NaN). The LeftFirst flag is used to control the order in which operations with potentially visible side-effects are performed upon x and y. It is necessary because ECMAScript specifies left to right evaluation of expressions. If LeftFirst is true, the x parameter corresponds to an expression that occurs to the left of the y parameter's corresponding expression. If LeftFirst is false, the reverse is the case and operations must be performed upon y before x. It performs the following steps when called:

1.  1\. If the LeftFirst flag is true, then
    1.  a. Let px be ? [ToPrimitive](https://tc39.es/ecma262/#sec-toprimitive)(x, number).
    2.  b. Let py be ? [ToPrimitive](https://tc39.es/ecma262/#sec-toprimitive)(y, number).
2.  2\. Else,
    1.  a. NOTE: The order of evaluation needs to be reversed to preserve left to right evaluation.
    2.  b. Let py be ? [ToPrimitive](https://tc39.es/ecma262/#sec-toprimitive)(y, number).
    3.  c. Let px be ? [ToPrimitive](https://tc39.es/ecma262/#sec-toprimitive)(x, number).
3.  3\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(px) is String and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(py) is String, then
    1.  a. If [IsStringPrefix](https://tc39.es/ecma262/#sec-isstringprefix)(py, px) is true, return false.
    2.  b. If [IsStringPrefix](https://tc39.es/ecma262/#sec-isstringprefix)(px, py) is true, return true.
    3.  c. Let k be the smallest non-negative [integer](https://tc39.es/ecma262/#integer) such that the code unit at index k within px is different from the code unit at index k within py. (There must be such a k, for neither String is a prefix of the other.)
    4.  d. Let m be the [integer](https://tc39.es/ecma262/#integer) that is the numeric value of the code unit at index k within px.
    5.  e. Let n be the [integer](https://tc39.es/ecma262/#integer) that is the numeric value of the code unit at index k within py.
    6.  f. If m < n, return true. Otherwise, return false.
4.  4\. Else,
    1.  a. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(px) is BigInt and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(py) is String, then
        1.  i. Let ny be ! [StringToBigInt](https://tc39.es/ecma262/#sec-stringtobigint)(py).
        2.  ii. If ny is NaN, return undefined.
        3.  iii. Return [BigInt::lessThan](https://tc39.es/ecma262/#sec-numeric-types-bigint-lessThan)(px, ny).
    2.  b. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(px) is String and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(py) is BigInt, then
        1.  i. Let nx be ! [StringToBigInt](https://tc39.es/ecma262/#sec-stringtobigint)(px).
        2.  ii. If nx is NaN, return undefined.
        3.  iii. Return [BigInt::lessThan](https://tc39.es/ecma262/#sec-numeric-types-bigint-lessThan)(nx, py).
    3.  c. NOTE: Because px and py are primitive values, evaluation order is not important.
    4.  d. Let nx be ? [ToNumeric](https://tc39.es/ecma262/#sec-tonumeric)(px).
    5.  e. Let ny be ? [ToNumeric](https://tc39.es/ecma262/#sec-tonumeric)(py).
    6.  f. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(nx) is the same as [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(ny), return [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(nx)::lessThan(nx, ny).
    7.  g. [Assert](https://tc39.es/ecma262/#assert): [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(nx) is BigInt and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(ny) is Number, or [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(nx) is Number and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(ny) is BigInt.
    8.  h. If nx or ny is NaN, return undefined.
    9.  i. If nx is \-∞𝔽 or ny is +∞𝔽, return true.
    10.  j. If nx is +∞𝔽 or ny is \-∞𝔽, return false.
    11.  k. If [ℝ](https://tc39.es/ecma262/#ℝ)(nx) < [ℝ](https://tc39.es/ecma262/#ℝ)(ny), return true; otherwise return false.

```
Note 1

Step [3](https://tc39.es/ecma262/#step-arc-string-check) differs from step [2.c](https://tc39.es/ecma262/#step-binary-op-string-check) in the algorithm that handles the addition operator `+` ([13.15.3](https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator)) by using the logical-and operation instead of the logical-or operation.
```

```
Note 2

The comparison of Strings uses a simple lexicographic ordering on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode specification. Therefore String values that are canonically equal according to the Unicode standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalized form. Also, note that for strings containing supplementary characters, lexicographic ordering on sequences of UTF-16 code unit values differs from that on sequences of code point values.
```

---

## 7.2.14 IsLooselyEqual ( x, y )

---

The abstract operation IsLooselyEqual takes arguments x (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)) and y (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It provides the semantics for the comparison x == y, returning true or false. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is the same as [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y), then
    1.  a. Return [IsStrictlyEqual](https://tc39.es/ecma262/#sec-isstrictlyequal)(x, y).
2.  2\. If x is null and y is undefined, return true.
3.  3\. If x is undefined and y is null, return true.
4.  4\. NOTE: This step is replaced in section [B.3.6.2](https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec).
5.  5\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Number and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is String, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(x, ! [ToNumber](https://tc39.es/ecma262/#sec-tonumber)(y)).
6.  6\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is String and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is Number, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(! [ToNumber](https://tc39.es/ecma262/#sec-tonumber)(x), y).
7.  7\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is BigInt and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is String, then
    1.  a. Let n be ! [StringToBigInt](https://tc39.es/ecma262/#sec-stringtobigint)(y).
    2.  b. If n is NaN, return false.
    3.  c. Return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(x, n).
8.  8\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is String and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is BigInt, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(y, x).
9.  9\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Boolean, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(! [ToNumber](#sec-tonumber)(x), y).
10.  10\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is Boolean, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(x, ! [ToNumber](#sec-tonumber)(y)).
11.  11\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is either String, Number, BigInt, or Symbol and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is Object, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(x, ? [ToPrimitive](https://tc39.es/ecma262/#sec-toprimitive)(y)).
12.  12\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Object and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is either String, Number, BigInt, or Symbol, return [IsLooselyEqual](https://tc39.es/ecma262/#sec-islooselyequal)(? [ToPrimitive](https://tc39.es/ecma262/#sec-toprimitive)(x), y).
13.  13\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is BigInt and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is Number, or if [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Number and [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y) is BigInt, then
    1.  a. If x or y are any of NaN, +∞𝔽, or \-∞𝔽, return false.
    2.  b. If [ℝ](https://tc39.es/ecma262/#ℝ)(x) = [ℝ](https://tc39.es/ecma262/#ℝ)(y), return true; otherwise return false.
14.  14\. Return false.

---

## 7.2.15 IsStrictlyEqual ( x, y )

---

The abstract operation IsStrictlyEqual takes arguments x (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)) and y (an [ECMAScript language value](https://tc39.es/ecma262/#sec-ecmascript-language-types)). It provides the semantics for the comparison x === y, returning true or false. It performs the following steps when called:

1.  1\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is different from [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(y), return false.
2.  2\. If [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x) is Number or BigInt, then
    1.  a. Return ! [Type](https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values)(x)::equal(x, y).
3.  3\. Return ! [SameValueNonNumeric](https://tc39.es/ecma262/#sec-samevaluenonnumeric)(x, y).

Note

This algorithm differs from the [SameValue](https://tc39.es/ecma262/#sec-samevalue) Algorithm in its treatment of signed zeroes and NaNs.