Comparing strings
How do you find a word in a paper dictionary? First you look at the first letter. If the first letters match, you compare the second ones, then the third ones, until the letters differ.
JavaScript compares strings the same way, letter by letter. Only its "alphabet" is different, and the operators < and > sometimes give an unexpected order. The capital Z comes before the small a, and the string "10" is less than "9":
console.log("apple" < "banana"); // true
console.log("Zebra" < "apple"); // true
console.log("10" < "9"); // true
console.log("10" < 9); // falseLet's go through the output line by line:
"apple" < "banana"givestrue, as in a dictionary."Zebra" < "apple"givestruetoo, although a dictionary putsapplefirst."10" < "9"givestrue, although ten is greater than nine."10" < 9givesfalse: there is a number on the right, and the comparison works differently.
Let's find out where this order comes from.
Character by character, by code
Every character has a numeric character code. The method charCodeAt(i) returns the code of the character at index i. The codes come in these groups:
- digits — from
48to57; - capital Latin letters — from
65to90; - small Latin letters — from
97to122.
console.log("A".charCodeAt(0), "Z".charCodeAt(0), "a".charCodeAt(0)); // 65 90 97
console.log("1".charCodeAt(0), "9".charCodeAt(0)); // 49 57
console.log("app" < "apple", "Ann" === "ann"); // true falseThis is JavaScript's "alphabet": all capital Latin letters come before all small ones. In a dictionary Z and z stand side by side, and here the dictionary analogy stops working.
Two strings are compared character by character, from left to right:
- While the characters match, JavaScript moves on.
- At the first difference, the string whose character has the smaller code is less; the remaining characters no longer matter.
- If one string ends earlier and matches the start of the other, it is less:
"app" < "apple".
The widget below walks through these steps in a function isLess with a while loop. Press "Next step" and watch the counter i and the codes ca and cb: the answer appears at the first difference.
1function isLess(a, b) {2 let i = 0;3 while (i < a.length && i < b.length) {4 const ca = a.charCodeAt(i);5 const cb = b.charCodeAt(i);6 if (ca !== cb) {7 return ca < cb;8 }9 i++;10 }11 return a.length < b.length;12}13 14console.log(isLess("10", "9"));15console.log(isLess("app", "apple"));16console.log("10" < "9");
The script calls isLess("10", "9") and waits for the answer.
So "10" < "9" gives true: the first characters "1" and "9" differ, and the code of "1" is smaller.
If a number stands on one side, the string becomes a number, as with ==, and "10" < 9 compares 10 with 9.
The === operator checks that two strings have the same characters in the same order, case included. That is why "Ann" === "ann" gives false.
Interviewers like to ask this: "Why does "10" < "9" give true?" The answer has two parts:
- both sides are strings, so they are compared character by character by code;
- the code of
"1"is less than the code of"9", and the comparison goes no further.
Alphabetical order
The method a.localeCompare(b) compares strings by the rules of a language and returns:
- a negative number if
acomes beforeb; - a positive number if
acomes after; - zero for equal strings.
A language and its rules are called a locale. Its code goes in the second argument: "ru", "en".
console.log("Zebra".localeCompare("apple") < 0); // false
console.log("apple".localeCompare("Zebra", "en") < 0); // true
console.log("apple".localeCompare("apple")); // 0Unlike <, localeCompare puts "Zebra" after "apple", as a dictionary does. Cyrillic is compared by codes too, and the letter ё has a larger code than я. That is why "ёж" < "яма" gives false, while "ёж".localeCompare("яма", "ru") returns a negative number: alphabetically, ё stands next to е.
Common mistake
Numbers read from text are compared as strings:
const a = "100";
const b = "25";
console.log(a > b); // ✗The program prints false, although 100 is greater than 25. Both sides are strings, and the comparison stopped at the first character: "1" is less than "2". Turn the strings into numbers before comparing: Number(a) > Number(b) gives true.
Key points
<and>compare strings character by character by character code, and the first difference decides.- That is why
"Zebra" < "apple"and"10" < "9"givetrue, and the start of a string is less than the whole string. - If a number stands on one side, the string becomes a number.
- For alphabetical order, use
localeCompare; compare numbers from text afterNumber.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.