Багато з операторів порівняння нам відомі з математики.
В 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для таких значень.
Коментарі
<code>, для кількох рядків – обгорніть їх тегом<pre>, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)