Почему null считается объектом в JavaScript: Руководство
Узнайте, почему в JavaScript null классифицируется как объект, разберитесь в различиях между null и undefined, лучшие практики и как избежать типичных ошибок.
Почему null считается объектом в JavaScript, и в чём разница между null и undefined?
В JavaScript null часто вызывается сомнениями, так как он классифицируется как тип object, хотя предназначен для обозначения отсутствия любого объектного значения. Я хотел бы понять:
-
Почему
nullсчитается объектом в JavaScript, хотя он предназначен для представления отсутствия любого объектного значения? -
Какова практическая разница между проверкой на
nullтак:javascriptif (object == null) { // Do something }и использованием проверки на ложность:
javascriptif (!object) { // Do something } -
Какие ключевые различия между
nullиundefinedв JavaScript, и когда следует использовать каждый из них?
Историческое объяснение: почему null считается объектом
Причина в том, что в ранней реализации JavaScript в 1990‑х годах null представлялся как NULL‑указатель (0x00) с тем же типовым тегом, что и объекты (0). Это историческое «ошибочное» поведение сохранилось для обратной совместимости, хотя концептуально null не является объектом.
“Или: типовый тег объекта плюс ссылка, равная нулю. Теперь должно быть очевидно, почему typeof думал, что null — объект: он смотрел на типовый тег, и тег говорил «объект».”
Эта реализационная деталь так и осталась, потому что слишком много кода зависит от этого поведения. Как объясняется в статье The odd history of JavaScript’s null, то, что было бы быстрым техническим «шорткатом», превратилось в долговременную странность языка.
Практические различия между null и undefined
Ключевое различие заключается в назначении и использовании:
| Аспект | null | undefined |
|---|---|---|
| Происхождение | Явно присвоенное значение | Значение по умолчанию для неинициализированных переменных |
| typeof | Возвращает “object” (баг) | Возвращает “undefined” |
| JSON | Действительное значение JSON | Убирается при сериализации |
| Глобальный объект | Не является свойством глобального объекта | Является свойством глобального объекта |
| Присваивание | Требует явного присваивания | Автоматически присваивается неинициализированным переменным |
Как отмечает kettanaito.com, «undefined используется для описания отсутствия значения, потому что мы не знаем, существует ли оно, тогда как null описывает отсутствие значения, потому что мы знаем, что его нет».
При сравнении null == undefined с оператором нестрогого равенства результат true, но null === undefined возвращает false. Это тонкое различие критично для операций, чувствительных к типу.
Сравнение null == null vs !object checks
Разница между этими двумя подходами значительна:
// Check 1: Explicit null check
if (object == null) {
// Это эквивалентно object === null || object === undefined
// Перехватывает как null, так и undefined
}
// Check 2: Falsy check
if (!object) {
// Это ловит все ложные значения: null, undefined, 0, "", false, NaN
// Может вызвать непредвиденные побочные эффекты
}
Как объясняет GeeksforGeeks, использование object == null — распространённый шаблон в JavaScript для проверки как null, так и undefined одним выражением. Однако такой подход может сбивать с толку, поскольку он смешивает два разных понятия.
Проверка !object более широка и может ловить значения, которые вы не намерены обрабатывать, например число 0 или пустую строку. Для более точного контроля рассмотрите:
// Explicit null check
if (object === null) {
// Обрабатывает только null
}
// Explicit undefined check
if (typeof object === 'undefined') {
// Обрабатывает только undefined
}
// Combined check
if (object == null) {
// Обрабатывает как null, так и undefined
}
Лучшие практики использования null и undefined
Когда использовать null
- Изначальное отсутствие: когда вы хотите явно указать, что значение должно быть пустым или отсутствовать
- Опциональные параметры: когда параметр функции должен быть опциональным, но иметь осмысленное значение по умолчанию
- Очистка данных: когда вы хотите намеренно очистить значение переменной
function processData(data = null) {
if (data === null) {
console.log('No data provided');
return;
}
// Process data
}
// Очистка переменной намеренно
let user = { name: 'John' };
user = null; // Явно очищаем ссылку
Когда использовать undefined
- Неинициализированные переменные: когда переменная объявлена, но ещё не присвоена
- Возврат функции: когда функция не возвращает ничего явно
- Отсутствующие свойства: когда свойство объекта отсутствует
// Неинициализированная переменная
let temp;
console.log(temp); // undefined
// Функция без return
function logMessage() {
console.log('Hello');
}
console.log(logMessage()); // undefined
// Отсутствующее свойство
const obj = { name: 'Alice' };
console.log(obj.age); // undefined
Как объясняет web.dev, «undefined в JavaScript указывает на отсутствие присвоенного значения, тогда как null означает намеренно пустое значение, заданное разработчиком».
Практические примеры
Обработка ответа API
// Плохой пример: использование falsy check
function handleResponse(response) {
if (!response) {
// Это ловит null, undefined, пустую строку и т.д.
console.error('No response');
return;
}
// Process response
}
// Хороший пример: явная проверка null/undefined
function handleResponse(response) {
if (response == null) {
// Ловит только null и undefined
console.error('No response received');
return;
}
// Process response
}
Валидация формы
// Используем null для намеренно пустых полей
function validateForm(formData) {
if (formData.email == null) {
return { valid: false, error: 'Email is required' };
}
// Additional validation
}
// undefined для отсутствующих данных формы
function handleSubmit() {
const formData = getFormData(); // Может вернуть undefined, если форма не найдена
if (formData == null) {
showNotification('Please fill out the form first');
return;
}
submitData(formData);
}
Сериализация JSON
// null сохраняется в JSON
const data = { name: 'John', age: null };
const json = JSON.stringify(data); // {"name":"John","age":null}
// undefined отбрасывается
const data2 = { name: 'John', age: undefined };
const json2 = JSON.stringify(data2); // {"name":"John"}
Как объясняет WebDevSimplified, «Устанавливая переменную в undefined, вы сообщаете, что переменная больше не содержит полезной информации, тогда как если значение равно null, вы конкретно говорите, что результат какого‑то действия не имеет значения».
Заключение
- Исторический артефакт:
nullсчитается объектом из‑за ранней реализации JavaScript, гдеnullиспользовал тот же типовый тег, что и объекты (0), создавая баг, который сохраняется для обратной совместимости. - Практическое различие: используйте
nullдля намеренного отсутствия объектов иundefinedдля неинициализированных переменных или системного отсутствия. Это делает ваш код более явным и поддерживаемым. - Тщательно проверяйте: при проверке отсутствующих значений
object == null— распространённый шаблон, ловящий какnull, так иundefined, тогда как!objectболее широк и ловит все ложные значения. Выбирайте в зависимости от конкретных потребностей. - Поведение JSON: помните, что
nullсохраняется при сериализации JSON, а свойства сundefinedотбрасываются, делаяnullболее предсказуемым для обмена данными. - Современные практики: в современном JavaScript с TypeScript или JSDoc
nullможно типизировать более точно, чемundefined, что делает его предпочтительным для намеренно пустых значений.
Понимание этих нюансов помогает писать более чистый, предсказуемый JavaScript и предотвращать распространённые ошибки, связанные с обработкой null и undefined.
Источники
- The history of “typeof null” - 2ality.com
- The odd history of JavaScript’s null - Medium
- Why typeof null === “object” in JavaScript? - DEV Community
- What is the difference between null and undefined in JavaScript? - Stack Overflow
- The Difference Between Null and Undefined - kettanaito.com
- null and undefined - web.dev
- JavaScript — Null vs. Undefined - codeburst.io