Операторы сравнения и логические значения

В этом разделе мы познакомимся с операторами сравнения и с логическими значениями, которые такие операторы возвращают.

Многие операторы сравнения знакомы нам из математики:

  • Больше/меньше: a > b, a < b.
  • Больше/меньше или равно: a >= b, a <= b.
  • Равно a == b. Для сравнения используется два символа равенства '='. Один символ a = b означал бы присваивание.
  • «Не равно». В математике он пишется как , в JavaScript – знак равенства с восклицательным знаком перед ним !=.

Логические значения

Как и другие операторы, сравнение возвращает значение. Это значение имеет логический тип.

Существует всего два логических значения:

  • true – имеет смысл «да», «верно», «истина».
  • false – означает «нет», «неверно», «ложь».

Например:

alert( 2 > 1 ); // true, верно
alert( 2 == 1 ); // false, неверно
alert( 2 != 1 ); // true

Логические значения можно использовать и напрямую, присваивать переменным, работать с ними как с любыми другими:

var a = true; // присваивать явно

var b = 3 > 4; // или как результат сравнения
alert( b ); // false

alert( a == b ); // (true == false) неверно, выведет false

Сравнение строк

Строки сравниваются побуквенно:

alert( 'Б' > 'А' ); // true
Осторожно, Unicode!

Аналогом «алфавита» во внутреннем представлении строк служит кодировка, у каждого символа – свой номер (код). JavaScript использует кодировку Unicode.

При этом сравниваются численные коды символов. В частности, код у символа Б больше, чем у А, поэтому и результат сравнения такой.

В кодировке Unicode обычно код у строчной буквы больше, чем у прописной.

Поэтому регистр имеет значение:

alert( 'а' > 'Я' ); // true, строчные буквы больше прописных

Для корректного сравнения символы должны быть в одинаковом регистре.

Если строка состоит из нескольких букв, то сравнение осуществляется как в телефонной книжке или в словаре. Сначала сравниваются первые буквы, потом вторые, и так далее, пока одна не будет больше другой.

Иными словами, больше – та строка, которая в телефонной книге была бы на большей странице.

Например:

  • Если первая буква первой строки больше – значит первая строка больше, независимо от остальных символов:

    alert( 'Банан' > 'Аят' );
  • Если одинаковы – сравнение идёт дальше. Здесь оно дойдёт до третьей буквы:

    alert( 'Вася' > 'Ваня' ); // true, т.к. 'с' > 'н'
  • При этом любая буква больше отсутствия буквы:

    alert( 'Привет' > 'Прив' ); // true, так как 'е' больше чем "ничего".

Такое сравнение называется лексикографическим.

Важно:

Обычно мы получаем значения от посетителя в виде строк. Например, prompt возвращает строку, которую ввел посетитель.

Числа, полученные таким образом, в виде строк сравнивать нельзя, результат будет неверен. Например:

alert( "2" > "14" ); // true, неверно, ведь 2 не больше 14

В примере выше 2 оказалось больше 14, потому что строки сравниваются посимвольно, а первый символ '2' больше '1'.

Правильно было бы преобразовать их к числу явным образом. Например, поставив перед ними +:

alert( +"2" > +"14" ); // false, теперь правильно

Сравнение разных типов

При сравнении значений разных типов, используется числовое преобразование. Оно применяется к обоим значениям.

Например:

alert( '2' > 1 ); // true, сравнивается как 2 > 1
alert( '01' == 1 ); // true, сравнивается как 1 == 1
alert( false == 0 ); // true, false становится числом 0
alert( true == 1 ); // true, так как true становится числом 1.

Тема преобразований типов будет продолжена далее, в главе Преобразование типов для примитивов.

Строгое равенство

В обычном операторе == есть «проблема» – он не может отличить 0 от false:

alert( 0 == false ); // true

Та же ситуация с пустой строкой:

alert( '' == false ); // true

Это естественное следствие того, что операнды разных типов преобразовались к числу. Пустая строка, как и false, при преобразовании к числу дают 0.

Что же делать, если всё же нужно отличить 0 от false?

Для проверки равенства без преобразования типов используются операторы строгого равенства === (тройное равно) и !==.

Если тип разный, то они всегда возвращают false:

alert( 0 === false ); // false, т.к. типы различны

Строгое сравнение предпочтительно, если мы хотим быть уверены, что «сюрпризов» не будет.

Сравнение с null и undefined

Проблемы со специальными значениями возможны, когда к переменной применяется операция сравнения > < <= >=, а у неё может быть как численное значение, так и null/undefined.

Интуитивно кажется, что null/undefined эквивалентны нулю, но это не так.

Они ведут себя по-другому.

  1. Значения null и undefined равны == друг другу и не равны чему бы то ни было ещё. Это жёсткое правило буквально прописано в спецификации языка.
  2. При преобразовании в число null становится 0, а undefined становится NaN.

Посмотрим забавные следствия.

Некорректный результат сравнения null с 0

Сравним null с нулём:

alert( null > 0 ); // false
alert( null == 0 ); // false

Итак, мы получили, что null не больше и не равен нулю. А теперь…

alert(null >= 0); // true

Как такое возможно? Если нечто «больше или равно нулю», то резонно полагать, что оно либо больше, либо равно. Но здесь это не так.

Дело в том, что алгоритмы проверки равенства == и сравнения >= > < <= работают по-разному.

Сравнение честно приводит к числу, получается ноль. А при проверке равенства значения null и undefined обрабатываются особым образом: они равны друг другу, но не равны чему-то ещё.

В результате получается странная с точки зрения здравого смысла ситуация, которую мы видели в примере выше.

Несравнимый undefined

Значение undefined вообще нельзя сравнивать:

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
  • Сравнения (1) и (2) дают false потому, что undefined при преобразовании к числу даёт NaN. А значение NaN по стандарту устроено так, что сравнения ==, <, >, <=, >= и даже === с ним возвращают false.
  • Проверка равенства (3) даёт false, потому что в стандарте явно прописано, что undefined равно лишь null и ничему другому.

Вывод: любые сравнения с undefined/null, кроме точного ===, следует делать с осторожностью.

Желательно не использовать сравнения >= > < <= с ними, во избежание ошибок в коде.

Итого

  • В JavaScript есть логические значения true (истина) и false (ложь). Операторы сравнения возвращают их.
  • Строки сравниваются побуквенно.
  • Значения разных типов приводятся к числу при сравнении, за исключением строгого равенства === (!==).
  • Значения null и undefined равны == друг другу и не равны ничему другому. В других сравнениях (с участием >,<) их лучше не использовать, так как они ведут себя не как 0.

Мы ещё вернёмся к теме сравнения позже, когда лучше изучим различные типы данных в JavaScript.

Карта учебника

Комментарии

перед тем как писать…
  • Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  • Для одной строки кода используйте тег <code>, для нескольких строк кода — тег <pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
  • Если что-то непонятно в статье — пишите, что именно и с какого места.