Comparison operators compare two values and always give back a boolean: true or false. Every decision a program makes starts with a comparison: is the password right, is the player out of lives, is the cart over $50? Getting comparisons right, especially when different types are involved, is what makes those decisions reliable.
Given let x = 5;, here is what each operator returns:
| Operator | Meaning | Comparing | Returns |
|---|---|---|---|
| == | equal to | x == 8 | false |
| x == 5 | true | ||
| x == "5" | true | ||
| === | equal value and equal type | x === 5 | true |
| x === "5" | false | ||
| != | not equal | x != 8 | true |
| !== | not equal value or not equal type | x !== 5 | false |
| x !== "5" | true | ||
| x !== 8 | true | ||
| > | greater than | x > 8 | false |
| < | less than | x < 8 | true |
| >= | greater than or equal to | x >= 8 | false |
| <= | less than or equal to | x <= 8 | true |
The highlighted results are the ones to study: comparing the number 5 with the string "5" gives different answers depending on the operator.
This is one of the most important distinctions in JavaScript.
== (loose equality) converts the values to the same type first, then compares=== (strict equality) compares value and type, with no conversion. Different types are never equalconsole.log(5 == "5"); // "5" converted to 5, then compared
console.log(5 === "5"); // number vs string: different types
console.log(0 == false); // false converted to 0
console.log(0 === false); // number vs boolean
console.log("" == false); // both converted to 0
console.log("" === false); // string vs boolean
The loose results look reasonable one at a time, but they add up to rules that are hard to predict. Is an empty string equal to false? With ==, yes, which is rarely what you meant.
The same split applies to "not equal": != converts first, !== does not. 5 != "5" is false (they are loosely equal), while 5 !== "5" is true.
=== and !== by default. With strict equality, what you see is what you get: if the types differ, the answer is false. If you need to compare a string to a number, convert it yourself first (shown below), so the conversion is visible in your code.
There is one case where loose equality is sometimes used on purpose. null and undefined are loosely equal to each other, and to nothing else:
console.log(null == undefined); // both mean "no value"
console.log(null === undefined); // but they are different types
console.log(null == 0); // null is not loosely equal to 0
So value == null is a shorthand some programmers use to mean "is this null or undefined?". You will see it in other people's code. Writing it out with === is clearer while you are learning.
All the comparison operators also work on strings. == and === check if two strings are exactly the same, character for character, including capitals:
console.log("cat" === "cat");
console.log("cat" === "Cat");
< and > compare strings alphabetically, one character at a time from the left, using each character's code number:
console.log("A" < "B"); // A comes before B
console.log("apple" < "banana"); // a comes before b
console.log("Zebra" < "apple"); // capitals come before ALL lowercase
That last one surprises people. Every uppercase letter has a lower code number than every lowercase letter (Z is 90, a is 97), so "Zebra" sorts before "apple".
"20" < "5" is true, because the first characters are compared first and "2" comes before "5". The same reason makes "2" > "12" true. Like sorting words in a dictionary, the length does not matter, only the characters from the left.
Comparing a string with a number can give unexpected results. With <, >, and ==, JavaScript converts the string to a number first:
"12" becomes 120"John", converts to NaN, and any comparison with NaN is false| Case | Result | Why |
|---|---|---|
| 2 < 12 | true | two numbers |
| 2 < "12" | true | "12" converted to 12 |
| 2 < "John" | false | "John" becomes NaN |
| 2 > "John" | false | NaN again: both directions false |
| 2 == "John" | false | NaN is not equal to anything |
| "2" < "12" | false | two strings: "2" vs "1" as characters |
| "2" > "12" | true | two strings: alphabetical |
| "2" == "12" | false | different strings |
Notice the pattern: one string and one number compares numerically, but two strings compare alphabetically. The same-looking values can give opposite answers.
Values typed into a web page (a form box, a prompt) always arrive as strings. To compare them reliably, convert them to numbers yourself with Number(), and check the conversion worked with isNaN() ("is Not a Number?"):
let input = "17"; // imagine this came from a form
let age = Number(input); // now the number 17
if (isNaN(age)) {
console.log("Input is not a number");
} else if (age < 18) {
console.log("Too young to vote");
} else {
console.log("Old enough to vote");
}
Change input to "abc" and Number() gives NaN, so the first branch catches it instead of making a wrong decision. The if / else structure used here gets its own lessons next.
Which comparison is false?
10 == "10"10 === "10"10 !== "10"10 >= 10What does this log?
console.log("100" < "9");
console.log("100" < 9);
true then false. Two strings compare alphabetically, and "1" comes before "9". With one number involved, "100" converts to 100, and 100 is not less than 9.A form gives you let qty = "3";. What is the most reliable way to check whether it equals 3?
qty == 3qty === 3Number(qty) === 3qty = 3qty.null == undefined and null === undefined and run it again"banana" > "apple", then "banana" > "Apple". Explain the second answer"10" > "9" as strings, then as numbers using Number() on both sides5 < "John" and 5 > "John". Why are both false?