Menu
Русский

null и undefined в JavaScript: в чём разница и что выбрать

Разбираемся, чем null отличается от undefined в JavaScript, как корректно проверить переменную на оба значения и что из этого стоит использовать в своём коде.

Два способа сказать «ничего»

В большинстве языков для обозначения «пустоты» есть одно значение. В JavaScript их целых два: null и undefined. Они ведут себя достаточно похоже, чтобы запутать новичков, и достаточно по-разному, чтобы подставить опытных разработчиков. Разобраться в этой разнице стоит — минут десять вашего времени это точно окупит.

Если коротко:

  • undefined — то, что JavaScript подставляет сам, когда чего-то не хватает.
  • null — то, что вы пишете сами, когда хотите явно сказать: «здесь намеренно пусто».
index.js
Output
Click Run to see the output here.

Обратите внимание на закономерность: каждый undefined выше появился потому, что JavaScript не смог найти значение. А null возник потому, что кто-то явно его написал.

Откуда берётся undefined

undefined всплывает в нескольких конкретных ситуациях, и все они — вариации на тему «значения попросту нет»:

index.js
Output
Click Run to see the output here.

В каждом из этих случаев JavaScript пошёл за значением и ничего не нашёл. undefined — это способ движка сказать: «Я посмотрел, значения там не было».

Технически undefined можно присвоить и самому (let x = undefined;), но так делать не стоит. Пусть undefined останется сигналом «JavaScript ничего не нашёл». А когда решение принимаете вы — используйте null.

Откуда берётся null

null появляется только тогда, когда его кто-то написал руками. В этом и смысл — это осознанный маркер.

index.js
Output
Click Run to see the output here.

DOM API активно использует null: вызов document.getElementById("missing") вернёт именно null, а не undefined. Браузер как бы говорит: «Я искал — такого элемента нет». То же самое с JSON.parse("null") — результат будет null, ведь в JSON вообще нет undefined.

Если коротко: undefined — это отсутствие значения по умолчанию, а null — отсутствие, которое мы выбрали сами.

typeof null: знаменитый баг

А теперь — легендарная странность:

index.js
Output
Click Run to see the output here.

То, что typeof null возвращает "object" — это баг из 1995 года, который нельзя было починить, не сломав кучу уже работающих сайтов, так что его оставили навсегда. null — это не объект, а примитив, как undefined, числа, строки и булевы значения. Просто typeof на этот счёт нагло врёт.

Отсюда практический вывод: для проверки на null оператор typeof бесполезен. Сравнивайте напрямую:

index.js
Output
Click Run to see the output here.

Или, что бывает чаще, проверить оба варианта сразу — об этом в следующем разделе.

Проверка на null и undefined: идиома == null

В большинстве случаев вам не важно, какое именно «пустое» значение пришло — нужно просто понять, есть что-то или нет, прежде чем с этим работать. Стандартный приём — нестрогое сравнение с null:

index.js
Output
Click Run to see the output here.

value == null возвращает true ровно для null и undefined и false для всего остального — включая 0, "" и false, что обычно как раз и нужно. Это тот самый редкий случай, когда == предпочтительнее ===. Линтеры об этом знают и такую проверку не ругают.

Если хочется написать явно — value === null || value === undefined означает ровно то же самое и читается без подвоха.

Операторы для null и undefined: ?? и ?.

В язык специально добавили два оператора, чтобы упростить работу с null и undefined. Оба считают эти два значения взаимозаменяемыми, а всё остальное не трогают.

Оператор нулевого слияния (??) подставляет значение по умолчанию, только если слева стоит null или undefined:

index.js
Output
Click Run to see the output here.

Сравни с ||, который заменит 0 на 3, потому что 0 — falsy-значение. ?? строже: он срабатывает только для двух nullish-значений.

Опциональная цепочка (?.) прерывает вычисление цепочки и возвращает undefined, как только натыкается на null или undefined:

index.js
Output
Click Run to see the output here.

Оба оператора существуют потому, что вопрос «а это значение nullish?» возникает буквально на каждом шагу. Подробнее мы разберём их дальше по курсу.

Значения по умолчанию срабатывают только для undefined

Тонкий, но важный момент: значения параметров по умолчанию подставляются только при undefined, но не при null.

index.js
Output
Click Run to see the output here.

Если передать null, это воспринимается как «я намеренно выбрал отсутствие значения», и функция это уважает. Хотите, чтобы null тоже запускал значение по умолчанию — используйте ?? внутри функции:

index.js
Output
Click Run to see the output here.

Эта разница регулярно сбивает с толку. Значения по умолчанию срабатывают на отсутствующий аргумент, а ?? — на nullish-аргумент (то есть null или undefined).

JSON и пропавший undefined

В JSON есть null, но нет undefined. Из-за этого при сериализации случаются тихие сюрпризы:

index.js
Output
Click Run to see the output here.

Поле age просто исчезло — JSON.stringify выбрасывает свойства со значением undefined. А вот null выживает, потому что JSON его поддерживает. Прогон объекта через JSON туда-обратно — типичный сценарий, в котором свойства с undefined тихо пропадают.

В массивах же undefined превращается в null:

index.js
Output
Click Run to see the output here.

Если вы проектируете payload для API, для полей «значения нет» лучше использовать null, а не undefined. Он переживёт сериализацию.

Когда что использовать: null или undefined

Разумное соглашение для вашего кода:

  • Пусть undefined означает «значение не передано» — пропущенные аргументы, необъявленные переменные, отсутствующие свойства. Вручную присваивать undefined не нужно.
  • null используйте, когда хотите явно сказать «тут намеренно пусто» — разлогиненный пользователь, невыбранная опция, очищенное поле формы.
  • На границах API принимайте оба варианта (через == null или ??), но сами возвращайте что-то одно, последовательно.

Некоторые стайл-гайды (в том числе у TypeScript) вообще отказываются от null и используют только undefined. Подход вполне рабочий — одно значение проще, чем два. Выберите правило на уровне проекта и придерживайтесь его везде.

Дальше: приведение типов

У null и undefined своё поведение, когда JavaScript приводит их к числу, строке или булеву значению: Number(null) даёт 0, а Number(undefined)NaN, и из-за такой асимметрии рождаются вполне реальные баги. Следующая тема — приведение типов, и как только вы увидите правила целиком, многие странности JavaScript перестанут казаться магией.

Часто задаваемые вопросы

В чём разница между null и undefined в JavaScript?

undefined означает, что значение ещё не присвоено — именно это JavaScript подсовывает вам для необъявленных переменных, пропущенных аргументов и отсутствующих свойств объекта. А null — это явное «здесь ничего нет», которое вы присваиваете сами и осознанно. Сам по себе JavaScript null никогда не возвращает, его нужно написать руками.

Как одной проверкой отловить и null, и undefined?

Пишите value == null. Нестрогое сравнение считает null и undefined равными друг другу, но не равными ничему другому, поэтому x == null истинно ровно для этих двух значений. Это тот редкий случай, когда == вместо === — идиоматично и безопасно.

Почему typeof null возвращает 'object'?

Это баг из самой первой версии JavaScript, который уже не починить — иначе половина веба сломается. typeof null возвращает 'object', хотя null — это примитив. Если нужно проверить именно на null, сравнивайте напрямую: value === null.

Что использовать в своём коде — null или undefined?

Пусть undefined означает «значение не передали», а null используйте тогда, когда хотите явно сказать «здесь осознанно пусто». Во многих проектах (и в style guide TypeScript) от null отказываются вовсе и обходятся одним undefined. Главное — выберите одну конвенцию на проект и придерживайтесь её.

Учитесь программировать с Coddy

НАЧАТЬ