typeof и необъявленная переменная в JavaScript
Что будет, если вызвать typeof на необъявленной переменной?
Теория по задаче
Оператор typeof является унарным оператором JavaScript, который возвращает строку с типом значения. Особенность typeof состоит в том, что он умеет безопасно обрабатывать обращение к идентификатору, которого не существует в текущей области видимости: вместо выброса исключения возвращается строка undefined.
undefined — это результат typeof, а не само значение переменной; то есть возвращается именно текст undefined.Почему ошибки нет: ключевая особенность typeof
В обычном выражении обращение к необъявленной переменной вызывает ReferenceError, потому что движок пытается получить значение по имени, но не находит привязку (binding) в окружениях выполнения.
У typeof сделано исключение: при проверке идентификатора, который невозможно разрешить (unresolvable reference), результатом становится строка undefined, а исключение не выбрасывается. Это исторически и спецификационно закреплённое поведение, чтобы можно было проверять наличие глобальных переменных (например, API окружения) без риска падения программы.
// Необъявленная переменная (не существует нигде)
typeof notDeclared; // "undefined"
// То же самое, но обычное чтение значения:
notDeclared; // ReferenceError: notDeclared is not defined
Важное отличие: "необъявлена" и "в TDZ"
Термины часто путаются, но ситуации разные:
- Необъявленная переменная: идентификатор вообще не был объявлен через
var,let,const,function,class,importв доступных областях видимости - Объявленная, но недоступная из-за TDZ (temporal dead zone): переменная объявлена через
let/const/class, но обращение происходит до выполнения строки инициализации
Для TDZ исключение из правила typeof не применяется: при обращении к переменной в TDZ будет выброшен ReferenceError, даже если используется typeof.
// Пример TDZ
{
// Переменная объявлена ниже, но сейчас она в TDZ
typeof tdzVar; // ReferenceError: Cannot access 'tdzVar' before initialization
let tdzVar = 1;
}
typeof, важно, чтобы проверяемое имя не было объявлено как let/const в той же области ниже по коду, иначе возможен ReferenceError из-за TDZ.Как работает typeof на практике
typeof всегда возвращает строку. Самые типичные результаты:
typeof undefined; // "undefined"
typeof null; // "object" // историческая особенность языка
typeof 123; // "number"
typeof 10n; // "bigint"
typeof "txt"; // "string"
typeof true; // "boolean"
typeof Symbol("s"); // "symbol"
typeof function(){}; // "function"
typeof {}; // "object"
Отсюда видно, почему вариант “вернётся null” неверен: typeof не возвращает null ни в каком случае; он возвращает только строку.
Разбор вариантов из задания
- Будет выброшен
ReferenceError, потому что переменная не объявлена — неверно дляtypeofи необъявленной переменной; верно для обычного чтения значенияx - Вернётся строка
undefinedи ошибки не будет — верно (для действительно необъявленной переменной) - Вернётся
null, так как переменная отсутствует — неверно,typeofвозвращает строку, а неnull - Вернётся строка
not defined— неверно; такой строкиtypeofне возвращает (сообщение об ошибкеis not definedотносится кReferenceErrorпри обычном доступе)
Таблица: что будет в разных случаях
| Ситуация | Пример | Результат |
|---|---|---|
| Имя не объявлено нигде | typeof noSuchName | "undefined" |
| Обычное чтение несуществующего имени | noSuchName | ReferenceError |
var объявлена, но ещё undefined | var a; typeof a | "undefined" |
let/const в TDZ | { typeof b; let b = 1; } | ReferenceError |
| Объект и отсутствующее свойство | typeof obj.missing | "undefined" (если obj определён) |
| Сам объект не определён | typeof obj.missing | ReferenceError (потому что сначала нужно прочитать obj) |
typeof obj.missing безопасна только при гарантированно существующем obj. Если obj не объявлен, ошибка возникнет ещё до доступа к свойству.Наглядная схема рассуждения
Шаг 1: Это typeof Identifier?
├─ Да → Шаг 2
└─ Нет → обычные правила вычисления выражений
Шаг 2: Идентификатор существует в области видимости?
├─ Нет (unresolvable) → результат "undefined", без ошибки
└─ Да → Шаг 3
Шаг 3: Идентификатор в TDZ?
├─ Да → ReferenceError
└─ Нет → вернуть строку типа значения
Итого: при typeof на действительно необъявленной переменной возвращается строка undefined без ошибки; ReferenceError появляется при обычном обращении к имени или при typeof к переменной в TDZ.