Порівняння об’єктів у JavaScript

Різні інструменти порівняння в JavaScript та реалізація Object.is

pic

Привіт, красиві люди в Інтернеті.

Якщо ви коли-небудь ламали голову над тим, як працюють порівняння на зразок ==, ===, або 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

Ось план:

  1. Виправимо +0 та -0: Перевіримо їх поведінку через 1/value.
  2. Обробимо NaN: Використаємо Number.isNaN, щоб перевірити чи обидва значення — це NaN.
  3. Резервний варіант: Для всього іншого просто використовуємо ===.

Ось як це виглядатиме в коді:

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

Leave a Reply

Your email address will not be published. Required fields are marked *