Equality: == vs === vs Object.is
В одной фразе: === — строгое сравнение без coercion; == — абстрактное равенство со сложным алгоритмом из спецификации; Object.is — как ===, но корректно обрабатывает NaN и -0. На собесе просят назвать corner cases и объяснить когда применять каждый.
// NaN — единственное значение, не равное самому себе (IEEE 754)console.log(NaN === NaN); // falseconsole.log(Object.is(NaN, NaN)); // true — правильная проверка
// Глобальный isNaN() сначала приводит к числу — ловушка!isNaN('foo'); // true ('foo' → NaN → true) — ложная тревогаNumber.isNaN('foo'); // false — нет coercion, только точная проверкаNumber.isNaN(NaN); // true// -0 vs +0: === не различает, Object.is — даconsole.log(-0 === +0); // trueconsole.log(Object.is(-0, +0)); // false
// Почему это важно:const direction = -0;console.log(1 / direction); // -Infinity — знак несёт смыслconsole.log(String(-0)); // '0' — toString скрывает знакconsole.log(JSON.stringify(-0)); // '0' — JSON тоже// == Abstract Equality: ключевые правилаconsole.log(null == undefined); // true (особый случай спецификации)console.log(null == 0); // false (null == только null/undefined)console.log(null == false); // falseconsole.log('' == false); // true ('' → 0, false → 0)console.log('0' == false); // true ('0' → 0, false → 0)console.log(0 == false); // true (false → 0)
// Практическое правило: == уместен для null-checkconst val = null;val == null; // true — поймает и null, и undefined (но не 0/''/'false')Итог: Используй === по умолчанию. Object.is — когда нужна точность с NaN и -0. == уместен только как null/undefined-check: val == null.