Багато з операторів порівняння нам відомі з математики.
В JavaScript вони записуються ось так:
- Більше/менше:
a > b
,a < b
. - Більше/менше або дорівнює:
a >= b
,a <= b
. - Дорівнює:
a == b
. Зверніть увагу, для порівняння потрібно використовувати два знаки рівності==
. Один знак рівностіa = b
означав би присвоєння. - Не дорівнює: в математиці позначається символом
≠
, проте в JavaScript записується якa != b
.
В цьому розділі ми вивчимо різні типи порівнянь, дізнаємось, як JavaScript їх виконує, та розглянемо важливі особливості.
В кінці ви знайдете корисні поради, як уникати специфічних “примх” JavaScript.
Результат порівняння має логічний тип
Всі оператори порівняння повертають значення логічного типу:
true
– означає “так”, “правильно” або “істина”.false
– означає “ні”, “неправильно” або “хибність”.
Наприклад:
alert( 2 > 1 ); // true (правильно)
alert( 2 == 1 ); // false (неправильно)
alert( 2 != 1 ); // true (правильно)
Результат порівняння можна присвоїти змінній, як і будь-яке інше значення:
let result = 5 > 4; // присвоїти результат порівняння змінній result
alert( result ); // true
Порівняння рядків
Щоб визначити, чи один рядок більший за інший, JavaScript використовує так званий “алфавітний” або “лексикографічний” порядок.
Інакше кажучи, рядки порівнюються посимвольно.
Наприклад:
alert( 'Я' > 'А' ); // true
alert( 'Соки' > 'Сода' ); // true
alert( 'Комар' > 'Кома' ); // true
Алгоритм порівняння рядків досить простий:
- Порівнюються перші символи обох рядків.
- Якщо перший символ першого рядка більший (менший) за перший символ другого рядка, то перший рядок більший (менший) за другий. Порівняння закінчено.
- В іншому випадку, якщо перші символи обох рядків рівні, то таким самим чином порівнюються вже другі символи рядків.
- Порівняння продовжується до того часу, доки не закінчиться один з рядків.
- Якщо два рядки закінчуються одночасно, то вони рівні. Інакше, довший рядок вважатиметься більшим.
В прикладах вище, порівняння 'Я' > 'А'
завершиться на першому кроці.
Проте друге порівняння слів 'Соки'
і 'Сода'
буде виконуватися посимвольно:
С
дорівнюєС
.о
дорівнюєо
.к
більше ніжд
. На цьому кроці порівнювання закінчується. Перший рядок більший.
Такий алгоритм порівняння схожий на алгоритм сортування, який використовується в словниках і телефонних довідниках, проте вони не зовсім однакові.
Наприклад, в JavaScript має значення регістр символів. Велика буква "А"
не рівна маленькій "а"
. Але яка з них більше? Маленька буква "а"
. Чому? Тому що маленькі букви мають більший код у внутрішній таблиці кодування, яку використовує JavaScript (Unicode). Ми розглянемо особливості і наслідки цього кодування в розділі Рядки.
Порівняння різних типів
Коли порівнюються значення різних типів, JavaScript конвертує ці значення в числа.
Наприклад:
alert( '2' > 1 ); // true, рядок '2' стає числом 2
alert( '01' == 1 ); // true, рядок '01' стає числом 1
Логічне значення true
стає 1
, а false
— 0
.
Наприклад:
alert( true == 1 ); // true
alert( false == 0 ); // true
Можлива наступна ситуація:
- Два значення рівні.
- Одне з них
true
як логічне значення, а інше —false
.
Наприклад:
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
З погляду JavaScript, результат очікуваний. Порівняння перетворює значення на числа (тому "0"
стає 0
), тоді як явне перетворення за допомогою Boolean
використовує інший набір правил.
Строге порівняння
Використання звичайного оператора порівняння ==
може викликати проблеми. Наприклад, він не відрізняє 0
від false
:
alert( 0 == false ); // true
Така ж проблема станеться з пустим рядком:
alert( '' == false ); // true
Це відбувається тому, що операнди різних типів перетворюються оператором порівняння ==
на числа. Пустий рядок, так само як false
, стане нулем.
Як тоді відрізнити 0
від false
?
Оператор строгої рівності ===
перевіряє рівність без перетворення типів.
Іншими словами, якщо a
і b
мають різні типи, то перевірка a === b
негайно поверне результат false
без спроби їхнього перетворення.
Перевірмо:
alert( 0 === false ); // false, тому що порівнюються різні типи
Є також оператор строгої нерівності !==
, аналогічний до !=
.
Оператор строгої рівності довше писати, проте він робить код більш зрозумілим і залишає менше місця для помилок.
Порівняння з null і undefined
Поведінка null
і undefined
під час порівняння з іншими значеннями — особливе:
- При строгому порівнянні
===
-
Ці значення різні, тому що різні їхні типи.
alert( null === undefined ); // false
- При нестрогому порівнянні
==
-
Ці значення рівні. Водночас ці значення не рівні значенням інших типів. Це спеціальне правило мови.
alert( null == undefined ); // true
- Під час використання математичних операторів та інших операторів порівняння
< > <= >=
-
Значення
null/undefined
конвертуються в числа:null
стає0
, тоді якundefined
стаєNaN
.
Тепер глянемо, які кумедні речі трапляються, коли ми застосовуємо ці правила. І, що більш важливо, як уникнути помилок під час їхнього використання.
Дивний результат порівняння null і 0
Порівняємо null
з нулем:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
З погляду математики це дивно. Результат останнього порівняння показує, що “null
більше або дорівнює нулю”, в такому випадку результат одного з порівнянь вище повинен бути true
, але вони обидва false
.
Причина в тому, що нестроге порівняння ==
і порівняння > < >= <=
працюють по-різному. Останні оператори конвертують null
в число, розглядаючи його як 0
. Ось чому вираз (3) null >= 0
дає true
, а вираз (1) null > 0
— false
.
З іншого боку, для нестрогого порівняння ==
значень undefined
і null
діє окреме правило: ці значення не перетворюються на інші типи, вони рівні один одному і не рівні будь-чому іншому. Ось чому вираз (2) null == 0
повертає результат false
.
Не порівнюйте значення undefined
Значення undefined
не має порівнюватись з іншими значеннями:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
Чому тоді порівняння undefined
з нулем завжди повертає false
?
Ми отримуємо такі результати, тому що:
- Порівняння
(1)
і(2)
повертаєfalse
, тому щоundefined
під час порівняння з “не null” значеннями завжди конвертується вNaN
, аNaN
— це спеціальне числове значення, яке завжди повертаєfalse
під час будь-яких порівнянь. - Нестроге порівняння
(3)
повертаєfalse
, тому щоundefined
рівне тількиnull
,undefined
і жодним іншим значенням.
Як уникати проблем
Чому ми переглядали ці приклади? Чи повинні ми постійно пам’ятати про всі ці особливості? Не обов’язково. З часом всі ці заплутані правила стануть для вас знайомими, але можна уникнути проблем, якщо дотримуватися надійних правил:
- Будьте пильні під час порівняння будь-якого значення з
undefined/null
, за винятком строгого порівняння===
. - Не використовуйте порівняння
>= > < <=
зі змінними, які можуть приймати значенняnull/undefined
, хіба що ви цілком впевнені в тому, що робите. Якщо змінна може приймати ці значення, то додайте для них окремі перевірки.
Підсумки
- Оператори порівняння повертають значення логічного типу.
- Рядки порівнюються посимвольно в лексикографічному порядку.
- Значення різних типів під час порівняння конвертуються в числа. Винятками є порівняння за допомогою операторів строгої рівності/нерівності.
- Значення
null
іundefined
рівні==
один одному і не рівні будь-якому іншому значенню. - Будьте обережні, використовуючи оператори порівняння на зразок
>
чи<
зі змінними, які можуть приймати значенняnull/undefined
. Хорошою ідеєю буде зробити окрему перевірку наnull/undefined
для таких значень.