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.
Проверьте себя
1. Что выведет console.log(typeof null)?
A"null"
B"object"
C"undefined"
D"number"
2. Что выведет console.log(NaN === NaN)?
Atrue
Bfalse
CNaN
DОшибку
3. В чём разница между null и undefined?
AЭто одно и то же значение
Bundefined ставит движок, null задаёт программист намеренно
Cnull — это число, undefined — строка
Dundefined нельзя присвоить переменной
Поддержать проект