typeof, null vs undefined, NaN — что отвечать
Три вечных вопроса про «пустые» значения и проверку типов.
undefined — значение не задано (переменная объявлена, но не присвоена). null — намеренное «пусто», которое присваивает программист.
null vs undefined
Разницу формулируют так: undefined ставит сам движок, когда значения ещё нет; null программист ставит осознанно, чтобы сказать «здесь специально ничего нет».
let x;
console.log(x); // объявлена, но не присвоена
const obj = {};
console.log(obj.missing); // нет такого свойства
let y = null; // намеренно пусто
console.log(y);
console.log(typeof undefined);
console.log(typeof null); // знаменитая историческая ошибка
console.log(null == undefined);
console.log(null === undefined);
Вывод:
undefined undefined null undefined object true false
Да, typeof null === "object" — это историческая ошибка языка, которую не стали чинить ради совместимости. Её любят спрашивать как «знаете ли вы тонкости».
NaN — «не число»
NaN (Not a Number) появляется при некорректных математических операциях. Главная каверза: NaN не равен ничему, включая сам себя.
console.log(0 / 0);
console.log(Number("abc"));
console.log(NaN === NaN); // не равен себе!
console.log(Number.isNaN(NaN));
console.log(typeof NaN);
Вывод:
NaN NaN false true number
Поэтому проверять на NaN через === NaN бесполезно — нужен Number.isNaN(x). Глобальный isNaN хуже: он сначала приводит аргумент к числу, поэтому isNaN("abc") тоже true.
Как безопасно проверять «пустоту»
На практике часто нужно одной проверкой отловить и null, и undefined — например, для необязательного аргумента или поля, которого может не быть. Здесь как раз уместно нестрогое == null: оно истинно ровно для этих двух значений и ни для чего больше. А чтобы взять значение по умолчанию именно при null/undefined (но сохранить 0 и ""), используют оператор ?? — в отличие от ||, он не сработает на «ложных, но валидных» значениях.
console.log(Number.isNaN("abc")); // строка — не NaN-число
console.log(isNaN("abc")); // глобальный приводит к числу
Вывод:
false true
Как отличить значения
| Значение | typeof | Когда возникает |
undefined | "undefined" | переменная без значения, отсутствующее свойство |
null | "object" | программист задал «пусто» вручную |
NaN | "number" | некорректная математика |
Итог
undefined— «значения ещё нет»,null— «значения намеренно нет».typeof null === "object"— историческая ошибка языка.NaNне равен самому себе; проверяйте черезNumber.isNaN.