Нестроге (==) проти строгого (===) порівняння
==, це нестроге порівняння, яке спершу приводить операнди до спільного типу, а ===, це строге порівняння, яке вимагає однакового типу і однакового значення. Різниця в одному символі змінює результат: 0 == false дає true, а 0 === false дає false.
Теорія
TL;DR
==перетворює типи перед порівнянням,===не перетворює нічого.- Для
===результатtrueможливий лише тоді, коли тип і значення збігаються. null == undefined, цеtrue, алеnull === undefined, цеfalse.- Правила приведення в
==неочевидні, тому саме на них народжуються баги з даними від користувача або з API. - Стандарт де-факто: усюди
===і!==, а==лише у форміvalue == null.
Швидкий приклад
console.log(5 == '5'); // true, типи приведено
console.log(5 === '5'); // false, число проти рядка
console.log(0 == false); // true, false стає 0
console.log(0 === false); // false, число проти булевого значенняОператор ==, нестроге (абстрактне) порівняння
== перетворює типи операндів перед порівнянням. Тобто JavaScript намагається «вгадати», чи рівні значення після приведення типів.
Приклади:
5 == '5' // true -> рядок '5' перетворюється на число 5
0 == false // true -> false приводиться до 0
null == undefined // true -> це єдиний випадок, коли вони рівні
' ' == 0 // true -> рядок із пробілів перетворюється на 0Небезпека: через неявні перетворення часто трапляються помилки, особливо під час перевірок користувацького введення або даних з API.
Оператор ===, строге порівняння
=== не робить перетворень типів. Операнди мають бути однакового типу і значення, щоб результат був true.
Приклади:
5 === '5' // false -> різні типи (число і рядок)
0 === false // false -> різні типи
null === undefined // false -> різні типи
5 === 5 // true -> однакове значення і типЯк саме == приводить типи
Порядок правил короткий, але його майже ніхто не пам'ятає напам'ять, і це головний аргумент проти ==:
- Якщо типи однакові, працює звичайне строге порівняння.
nullіundefinedрівні одне одному і більше нічому.- Число проти рядка: рядок перетворюється на число.
- Булеве значення з будь-якого боку спершу стає числом (
trueдає 1,falseдає 0). - Об'єкт проти примітива: об'єкт зводиться до примітива через
valueOf()абоtoString().
[] == false; // true, [] стає '', потім 0, а false теж 0
[1] == 1; // true, [1] стає '1', потім 1
'0' == false; // true, обидва зводяться до 0
'0' === false; // falseОбидва оператори однаково не рятують у двох особливих випадках: NaN не дорівнює самому собі, а +0 і -0 вважаються рівними. Для цих ситуацій є Object.is().
NaN === NaN; // false
Object.is(NaN, NaN); // true
Object.is(0, -0); // falseПідсумок: коли що використовувати
| Оператор | Приводить типи | Типове застосування |
|---|---|---|
=== / !== | ні | майже завжди, стандарт для будь-яких перевірок |
== / != | так | лише свідомо, у вигляді value == null |
Object.is() | ні | коли важливо розрізнити NaN і знак нуля |
Рекомендація: завжди використовуйте === (і !==), якщо немає особливої причини застосувати нестроге порівняння. Це робить код передбачуваним і знижує кількість багів. Виняток, який лишають навіть суворі лінтери, це перевірка if (value == null), бо вона коротко покриває і null, і undefined.
Типові помилки
- Перевіряють дані з форми чи API через
==. Введення завжди приходить рядком, тож'0' == falseдаєtrueі умова спрацьовує не так, як задумано. - Вважають, що
===порівнює вміст об'єктів. Для об'єктів обидва оператори порівнюють посилання:{} === {}, цеfalse. - Пишуть
x == NaN. Жодне порівняння зNaNне дастьtrue, потрібенNumber.isNaN(x). - Використовують
== nullне розуміючи, що робиться. Це навмисна перевірка одразу наnullіundefined, а не «менш строга» версія перевірки на порожнечу:0і''її не проходять. - Плутають
==з=. Одинарний знак, це присвоєння всередині умови, і воно завжди «істинне» для ненульового значення.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.