Сравнение строк
Как найти слово в бумажном словаре? Сначала смотрят на первую букву. Если первые буквы совпали, сравнивают вторые, потом третьи, пока буквы не разойдутся.
JavaScript сравнивает строки так же, буква за буквой. Только его «алфавит» другой, и операторы < и > иногда дают неожиданный порядок. Заглавная Z оказывается раньше строчной a, а строка "10" — меньше строки "9":
console.log("apple" < "banana"); // true
console.log("Zebra" < "apple"); // true
console.log("10" < "9"); // true
console.log("10" < 9); // falseРазберём вывод по строкам:
"apple" < "banana"даётtrue, как в словаре."Zebra" < "apple"тоже даётtrue, хотя в словареappleстоит раньше."10" < "9"даётtrue, хотя десять больше девяти."10" < 9даётfalse: справа число, и сравнение идёт по-другому.
Давайте выясним, откуда берётся такой порядок.
Посимвольно по кодам
У каждого символа есть числовой код символа. Метод charCodeAt(i) возвращает код символа с индексом i. Коды идут такими группами:
- у цифр — от
48до57; - у заглавных латинских букв — от
65до90; - у строчных латинских букв — от
97до122.
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 falseЭто и есть «алфавит» JavaScript: все заглавные латинские буквы идут раньше всех строчных. В словаре Z и z стоят рядом, и здесь аналогия со словарём перестаёт работать.
Две строки сравниваются посимвольно, слева направо:
- Пока символы совпадают, JavaScript идёт дальше.
- На первом различии меньше та строка, у которой код символа меньше; остальные символы уже не важны.
- Если одна строка кончилась раньше и совпадает с началом другой, она меньше:
"app" < "apple".
Виджет ниже проходит эти шаги в функции isLess с циклом while. Нажимайте «Следующий шаг» и следите за счётчиком i и кодами ca и cb: ответ появляется на первом различии.
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");
Скрипт вызывает isLess("10", "9") и ждёт ответ.
Отсюда "10" < "9" даёт true: первые символы "1" и "9" разные, а код "1" меньше.
Если с одной стороны число, строка превращается в число, как при ==, и "10" < 9 сравнивает 10 с 9.
Оператор === для строк проверяет, что символы и их порядок совпадают полностью, с учётом регистра. Поэтому "Ann" === "ann" даёт false.
Этот вопрос часто задают на собеседовании: «Почему "10" < "9" даёт true?» Ответ состоит из двух частей:
- обе стороны — строки, поэтому они сравниваются посимвольно по кодам;
- код
"1"меньше кода"9", и дальше сравнение не идёт.
Порядок по алфавиту
Метод a.localeCompare(b) сравнивает строки по правилам языка и возвращает:
- отрицательное число, если
aидёт раньшеb; - положительное число, если
aидёт позже; - ноль для равных строк.
Язык и его правила называют локалью. Её код передают вторым аргументом: "ru", "en".
console.log("Zebra".localeCompare("apple") < 0); // false
console.log("apple".localeCompare("Zebra", "en") < 0); // true
console.log("apple".localeCompare("apple")); // 0В отличие от <, localeCompare ставит "Zebra" после "apple", как в словаре. Кириллица тоже сравнивается по кодам, и у буквы ё код больше, чем у я. Поэтому "ёж" < "яма" даёт false, а "ёж".localeCompare("яма", "ru") возвращает отрицательное число: по алфавиту ё стоит рядом с е.
Частая ошибка
Числа, прочитанные из текста, сравнили как строки:
const a = "100";
const b = "25";
console.log(a > b); // ✗Программа печатает false, хотя 100 больше 25. Обе стороны — строки, и сравнение остановилось на первом символе: "1" меньше "2". Превратите строки в числа перед сравнением: Number(a) > Number(b) даёт true.
Главное
<и>сравнивают строки посимвольно по кодам символов, и решает первое различие.- Поэтому
"Zebra" < "apple"и"10" < "9"даютtrue, а начало строки меньше всей строки. - Если с одной стороны число, строка превращается в число.
- Для порядка по алфавиту берут
localeCompare, а числа из текста сравнивают послеNumber.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.