Різні інструменти порівняння в JavaScript та реалізація Object.is
Привіт, красиві люди в Інтернеті.
Якщо ви коли-небудь ламали голову над тим, як працюють порівняння на зразок ==
, ===
, або Object.is
в JavaScript, ви не самі.
Всі ці оператори призначені для перевірки, чи є два значення "рівними", але вони не завжди поводяться однаково.
Давайте розберемо це простими словами і навіть створимо свою версію Object.is
.
Інструменти для порівняння в JavaScript
1. ==
(Легке рівняння)
Це той хлопець, який намагається зробити все працюючим, навіть якщо типи не збігаються. Він каже:
“Гей, я перетворю одне значення, щоб воно відповідало іншому, а потім порівнюю.”
Приклад:
console.log(1 == '1'); // true (число перетворюється в рядок або навпаки)
console.log(false == 0); // true (false стає 0)
console.log(null == undefined); // true (вони схожі в цьому контексті)
Чому це може заплутати:
console.log('0' == false); // true (чекай, що?!)
Він намагається занадто сильно і іноді дає несподівані результати.
2. ===
(Суворе рівняння)
Це той хлопець, який не любить зайвої романтики. Він каже:
“Я не роблю жодних перетворень типів. Якщо тип або значення не збігаються, це false.”
Приклад:
console.log(1 === '1'); // false (різні типи)
console.log(false === 0); // false (немає перетворення типів)
Чому це краще:
Це простіше, але все ж є деякі нюанси, які він не враховує, такі як NaN
або +0
і -0
.
3. Object.is
Це перфекціоніст. Це як ===
, але з усуненими всіма тими дивними випадками.
- Він знає, що
NaN
рівне самому собі. - Він вміє розрізняти
+0
і-0
.
Приклад:
console.log(Object.is(NaN, NaN)); // true (наконец-то!)
console.log(Object.is(+0, -0)); // false (він знає, що це не одне і те саме)
Ось тут і знадобиться Object.is
.
Давайте створимо свій власний Object.is
Ось план:
- Виправимо
+0
та-0
: Перевіримо їх поведінку через1/value
. - Обробимо
NaN
: ВикористаємоNumber.isNaN
, щоб перевірити чи обидва значення — цеNaN
. - Резервний варіант: Для всього іншого просто використовуємо
===
.
Ось як це виглядатиме в коді:
const objectIs = (value1, value2) => {
// Обробка +0 та -0
if (value1 === 0 && value2 === 0) {
// ділення 1 на +0 дає Infinity
// ділення 1 на -0 дає -Infinity
// Тому ми порівнюємо Infinity та -Infinity
return 1 / value1 === 1 / value2;
}
// Обробка NaN
if (Number.isNaN(value1) && Number.isNaN(value2)) {
return true;
}
// Резервний варіант — суворе рівняння
return value1 === value2;
};
Тестуємо
Спеціальні випадки:
console.log(objectIs(+0, -0)); // false
console.log(objectIs(-0, -0)); // true
console.log(objectIs(+0, +0)); // true
console.log(objectIs(NaN, NaN)); // true
Звичайні порівняння:
console.log(objectIs(42, 42)); // true
console.log(objectIs('hello', 'hello')); // true
console.log(objectIs(null, null)); // true
console.log(objectIs(undefined, undefined)); // true
Об'єкти та масиви:
console.log(objectIs([], [])); // false (різні посилання в пам'яті)
console.log(objectIs({}, {})); // false (різні посилання в пам'яті)
console.log(objectIs([1], [1])); // false
Символи:
console.log(objectIs(Symbol('a'), Symbol('a'))); // false (унікальні символи)
console.log(objectIs(Symbol.for('a'), Symbol.for('a'))); // true (спільний глобальний символ)
Коли використовувати що?
- Використовуйте
==
, якщо вам потрібне перетворення типів (але, чесно кажучи, краще уникати цього). - Використовуйте
===
для більшості порівнянь — це просто і надійно. - Використовуйте
Object.is
, коли вас турбують крайні випадки, якNaN
або+0
/-0
.
Я завжди прагну вдосконалюватися і буду радий почути ваші думки! Якщо у вас є пропозиції, відгуки чи теми, які ви хочете, щоб я розглянув, будь ласка, діліться ними в коментарях нижче.
Ваші зауваження дуже цінні! 🙂
Перекладено з: Comparing Things in JavaScript