These four operators as you might have guessed are used for comparing values in JavaScript. The names of these operators are:

Operator | Name |
---|---|

`>` | Less than |

`>` | Greater than |

`<=` | Less than or equal |

`>=` | Greater than or equal |

They are part of a set of operators known as **comparison operators**. There are other comparison operators too(e.g. `==`

, `===`

, `!=`

and `!==`

) but they are not today's topic.

These operators are also part of a set of operators officially known as **relational operators**. Note that there are two **relational operators** (`in`

and `instanceof`

) that are not comparison operators.

To only refer to these four operators there is a precise term also: **ordering operators**. They are called ordering operators because they allow you to know the comparative position of two values. However this is very less known term and people might not immediately understand what you are talking about.

In this article we dig deep but in a pragmatic way into these four comparison operators.

## The less than operator: `<`

The art of knowing is knowing what to ignore. - Rumi

JavaScript attempts to compare any value you give to these operators. And there are lots of rules going on make that happen. Luckily we can ignore most of them if strange comparisons like comparing arrays to numbers or objects etc. are something not important to you or your team members.

To make life simple and easy, here I will ignore all the less useful comparisons and only go into the depth of the most useful ones:

- I will only write about the comparisons of Number, BigInt and String types.
- I will ignore the cases where the types of the operands differ(I think it's better to explicitly convert values to the same type before comparing them to make things clear).

### Comparing Number and BigInt types of values

#### Comparing Numbers

These are mostly as in mathematics. For example:

```
4 < 6 // true
10 < 9 // false
```

As values Number type have a limited precision, for very big numbers literals or numbers literals with a lots of digits after the decimal point, you might get incorrect result when comparing them. For example:

```
3 < 3.00000000000000001 // false
88888888888888888 <
88888888888888889 // false
```

This is because these numbers loose some precision when they are turned into values from literals.

For comparing `leftNumber < rightNumber`

where `leftNumber`

and `rightNumber`

are values(not literals!) of Number type, the following algorithm is used:

- If either value is
`NaN`

return`false`

. - If
`leftNumber`

is the same number as`rightNumber`

, return`false`

. - If
`leftNumber`

is`Infinity`

, return`false`

. - If
`rightNumber`

is`Infinity`

, return`true`

. - If
`leftNumber`

is`-Infinity`

, return`true`

. - If
`rightNumber`

is`-Infinity`

, return`false`

. - If
`leftNumber`

is less than`rightNumber`

as in mathematics, return`true`

. Otherwise return`false`

.

#### Comparing BigInt

As BigInts don't have `NaN`

or infinities, and they have arbitrary precision, they work just as fine as in mathematics.

```
88888888888888888n <
88888888888888889n // true
```

### Comparing Strings

`<`

operator uses a simple lexicographic ordering for comparing string values which can become handy when we know how it works and we don't need any advanced comparison.

**Info**: The heavy phrase "Lexicographic ordering" means nothing other than any ordering similar to the alphabetic ordering of the dictionaries.

#### A brief tour to Unicode

To understand string comparison, it's important to understand how JavaScript strings are made of.

For the dumb computers to make sense of JavaScript strings, they must be encoded in some way. JavaScript does it using **UTF-16**.

What is UTF-16? It stands for **16-bit Unicode Transformation Format**. But what's that mean? It means a string in JavaScript is a sequence of 16 bit code units. You might be asking what's a code unit?

Well a **code unit** is a number to encode a code point. What is a code point? A **codepoint** is also a number composed of a single 16 bit code unit or two 16 bit code units. Each character is encoded as one or more codepoints in unicode.

A string gets an index at each code unit holding a part of the string. Let's call each such this part a **string element**(this is not a unicode term).

The concept of **character** is hard to define. For simplicity we can define it like below:

- Any symbol that doesn't seems broken.
- The invisible things that allows you to do space, tabs and newlines.

We can write a function to get the decimal values of the code units of a string:

```
function getCodeUnits(s) {
let result = [];
for (let i = 0; i < s.length; i++) {
result.push(s.charCodeAt(i));
}
return result;
}
getCodeUnits("Hi 😄");
// [72, 105, 32, 55357, 56836]
getCodeUnits("I ❤️🔥 JS");
// [73, 32, 10084, 65039, 8205, 55357, 56613, 32, 74, 83]
```

Note that the 😄 emoji needs 2 code units and the ❤️🔥 needs 5 code units.

#### The string comparison algorithm

Let `leftString`

and `rightString`

are strings and we want to know how JavaScript evaluates the value of the expression `leftString < rightString`

. Here goes the algorithm:

If

`leftString`

starts with`rightString`

, return`false`

. For example:`'hello world' < 'hello' // false 'hello world' < '' // false, because every string starts with an empty string`

If

`rightString`

starts with`leftString`

, return`true`

. For example:`'hello' < 'hello world' // true '' < 'hello world' // true`

At this point, as neither string starts with the other, there must be a smallest index where code units of the string element of the two strings are different. Let

`s`

be that index. In the following example`s`

is`4`

:`'Linux' < 'Linus Torvalds' getCodeUnits('Linux'); // [76, 105, 110, 117, 120] getCodeUnits('Linus Torvalds'); // [76, 105, 110, 117, 115, 32, // 84, 111, 114, 118, 97, 108, 100, 115]`

Let

`m`

be`leftString.charCodeAt(s)`

.Let

`n`

be`rightString.charCodeAt(s)`

.If

`m < n`

return`true`

, otherwise return`false`

.For the example at step

,**3**`m`

is`120`

and`n`

is`115`

, so`'Linux' < 'Linus Torvalds'`

is`false`

!

Note that comparison with `<`

is not like dictionaries in all cases, for example when lowercase, uppercase or accents are involved. But for simple comparisons like comparing two lowercase English letters or words, it works just fine.

Luckily JavaScript now allows proper language aware comparison through the awesome Intl.Collator object, which is beyond the scope of this article.

## The other ones: `>`

, `<=`

and `>=`

They behave the same as their name suggests and you may stop reading further this article if you wish. But if you are curious, you are welcome 🤗

For these operators, here we again limit ourselves in the following ways:

- We will only deal with values of types Number, BigInt and String.
- Both operands will have the same type.

**Note**: JavaScript always ensures left to right evaluation of expressions. So inside the algorithms below the

`leftValue`

might go to the right and vice versa but the expressions that forms those values are always evaluated left to right.You don't need to remember or memorize these algorithms as you can easily predict their behaviors by their names. This is just for understanding their behavior in a deeper way.

### Greater than operator: `>`

`leftValue > rightValue`

can be described as below:

- If both operands are of Number type and either one is
`NaN`

- return
`false`

.

- return
- Return
`rightValue < leftValue`

### Less than or equal operator: `<=`

`leftValue <= rightValue`

can be described as below:

- If both operands are of Number type and either one is
`NaN`

- return
`false`

.

- return
- If
`rightValue < leftValue`

is`true`

- Return
`false`

- Return
- Else
- Return
`true`

- Return

### Greater than or equal operator: `>=`

`leftValue >= rightValue`

can be described as below:

- If both operands are of Number type and either one is
`NaN`

- return
`false`

.

- return
- If
`leftValue < rightValue`

is`true`

- Return
`false`

- Return
- Else
- Return
`true`

- Return