«Uncaught ReferenceError» — ваш первый враг? Учимся правильно проверять undefined в JavaScript
Каждый, кто писал на JavaScript хотя бы пару строк, сталкивался с загадочным undefined. Это не просто «пустое место» — это полноценный тип данных с собственным значением. Но как его правильно поймать? Если вы гуглили «How can I check for undefined in JavaScript», вы не одиноки: этот вопрос на Stack Overflow собрал сотни тысяч просмотров. Проблема в том, что в JS есть несколько способов проверки, и каждый таит подводные камни.
В этой статье мы разберём 5 подходов, от простого к сложному, сравним их производительность и надёжность, и выясним, какой метод стоит использовать в 2025 году. Поехали!
Что такое undefined на самом деле?
Прежде чем проверять, давайте договоримся о терминах. undefined — это примитивное значение, которое присваивается переменной, если её объявили, но не инициализировали:
let a;
console.log(a); // undefined
Важно: undefined ≠ null ≠ not defined. null — это намеренное «ничто», а not defined (ReferenceError) — когда переменная вообще не объявлена. Эти нюансы критичны для выбора правильной проверки.
Метод №1: Оператор typeof — золотой стандарт?
Самый популярный и безопасный способ — использовать typeof:
if (typeof x === 'undefined') {
console.log('x не определён');
}
Почему это работает даже для необъявленных переменных? typeof никогда не выбрасывает ReferenceError. Если переменная не существует, он просто возвращает строку "undefined".
Плюсы:
- Безопасен для необъявленных переменных
- Читаемый и понятный код
- Работает во всех браузерах и средах (Node.js, Deno)
Минусы:
- Длинноват для частого использования
- Может ввести в заблуждение новичков (строковое сравнение)
Вердикт: Лучший выбор для глобальных проверок и случаев, когда переменная может быть не объявлена.
Метод №2: Строгое сравнение с undefined (===)
Второй по популярности способ — сравнить значение напрямую:
if (x === undefined) {
console.log('x равен undefined');
}
Здесь есть нюанс: переменная должна быть объявлена. Если x не существует, вы получите ReferenceError. Поэтому такой код безопасен только для:
- Свойств объектов (
obj.prop === undefined) - Параметров функций
- Переменных, объявленных через
let,constилиvar
Подводный камень: глобальный undefined
В старых браузерах (IE 8 и ниже) undefined можно было перезаписать:
undefined = 'теперь я строка'; // Кошмар!
Сейчас это невозможно (в строгом режиме), но если вы поддерживаете легаси-код — лучше используйте typeof.
Вердикт: Отличный метод для локальных переменных и свойств объектов. Быстрый и лаконичный.
Метод №3: Оператор void
Малоизвестный, но элегантный способ — void 0:
if (x === void 0) {
console.log('x undefined');
}
Оператор void вычисляет выражение и возвращает undefined. void 0 — самый короткий способ получить чистое undefined, не зависящее от глобальной переменной.
Когда это полезно?
- В минифицированном коде (экономит байты)
- В библиотеках, где важна защита от переопределения
undefined - В функциональном программировании (например, в цепочках промисов)
Минус: Выглядит странно для новичков. Используйте только если уверены, что команда поймёт.
Вердикт: Технически идеальный, но нишевый метод.
Метод №4: hasOwnProperty и in — для объектов
Если вы проверяете, существует ли свойство у объекта (даже если его значение undefined), обычное сравнение не подойдёт:
const obj = { a: undefined, b: 42 };
console.log(obj.a === undefined); // true
console.log(obj.c === undefined); // true — но свойства c не существует!
Чтобы различить «свойство есть, но undefined» и «свойства нет», используйте:
if (obj.hasOwnProperty('a')) {
console.log('Свойство a существует');
}
if ('a' in obj) {
console.log('Свойство a есть в объекте (включая прототип)');
}
Разница между hasOwnProperty и in:
hasOwnProperty— только собственные свойства объектаin— собственные + унаследованные (из прототипа)
Вердикт: Обязателен к использованию при работе с динамическими объектами, JSON и конфигами.
Метод №5: Опциональная цепочка (?.) и нулевое слияние (??)
Современный JavaScript (ES2020+) предлагает более декларативные способы:
// Вместо:
if (user && user.profile && user.profile.name !== undefined) { ... }
// Пишем:
if (user?.profile?.name !== undefined) { ... }
Оператор ?? (nullish coalescing) проверяет только на null и undefined:
const name = user?.name ?? 'Аноним';
// Если user.name — undefined или null, берём 'Аноним'
Важно: ?? не сработает на false, 0 или пустую строку (в отличие от ||). Это баг или фича? Скорее фича — вы явно говорите: «дай значение, если оно не null/undefined».
Плюсы:
- Код становится короче и читаемее
- Убирает необходимость в глубоких проверках
Минусы:
- Не работают в старых средах (требуется транспиляция)
- Не подходят для необъявленных переменных
Вердикт: Современный стандарт для работы с объектами. Используйте смело, если проект на TypeScript или использует Babel.
Сравнительная таблица: какой метод выбрать?
Да