Другое

Почему null считается объектом в JavaScript: Руководство

Узнайте, почему в JavaScript null классифицируется как объект, разберитесь в различиях между null и undefined, лучшие практики и как избежать типичных ошибок.

Почему null считается объектом в JavaScript, и в чём разница между null и undefined?

В JavaScript null часто вызывается сомнениями, так как он классифицируется как тип object, хотя предназначен для обозначения отсутствия любого объектного значения. Я хотел бы понять:

  1. Почему null считается объектом в JavaScript, хотя он предназначен для представления отсутствия любого объектного значения?

  2. Какова практическая разница между проверкой на null так:

    javascript
    if (object == null) {
      // Do something
    }
    

    и использованием проверки на ложность:

    javascript
    if (!object) {
      // Do something
    }
    
  3. Какие ключевые различия между 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

Разница между этими двумя подходами значительна:

javascript
// 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 или пустую строку. Для более точного контроля рассмотрите:

javascript
// 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

  • Изначальное отсутствие: когда вы хотите явно указать, что значение должно быть пустым или отсутствовать
  • Опциональные параметры: когда параметр функции должен быть опциональным, но иметь осмысленное значение по умолчанию
  • Очистка данных: когда вы хотите намеренно очистить значение переменной
javascript
function processData(data = null) {
  if (data === null) {
    console.log('No data provided');
    return;
  }
  // Process data
}

// Очистка переменной намеренно
let user = { name: 'John' };
user = null; // Явно очищаем ссылку

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

  • Неинициализированные переменные: когда переменная объявлена, но ещё не присвоена
  • Возврат функции: когда функция не возвращает ничего явно
  • Отсутствующие свойства: когда свойство объекта отсутствует
javascript
// Неинициализированная переменная
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

javascript
// Плохой пример: использование 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
}

Валидация формы

javascript
// Используем 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

javascript
// 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, вы конкретно говорите, что результат какого‑то действия не имеет значения».

Заключение

  1. Исторический артефакт: null считается объектом из‑за ранней реализации JavaScript, где null использовал тот же типовый тег, что и объекты (0), создавая баг, который сохраняется для обратной совместимости.
  2. Практическое различие: используйте null для намеренного отсутствия объектов и undefined для неинициализированных переменных или системного отсутствия. Это делает ваш код более явным и поддерживаемым.
  3. Тщательно проверяйте: при проверке отсутствующих значений object == null — распространённый шаблон, ловящий как null, так и undefined, тогда как !object более широк и ловит все ложные значения. Выбирайте в зависимости от конкретных потребностей.
  4. Поведение JSON: помните, что null сохраняется при сериализации JSON, а свойства с undefined отбрасываются, делая null более предсказуемым для обмена данными.
  5. Современные практики: в современном JavaScript с TypeScript или JSDoc null можно типизировать более точно, чем undefined, что делает его предпочтительным для намеренно пустых значений.

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

Источники

  1. The history of “typeof null” - 2ality.com
  2. The odd history of JavaScript’s null - Medium
  3. Why typeof null === “object” in JavaScript? - DEV Community
  4. What is the difference between null and undefined in JavaScript? - Stack Overflow
  5. The Difference Between Null and Undefined - kettanaito.com
  6. null and undefined - web.dev
  7. JavaScript — Null vs. Undefined - codeburst.io
Авторы
Проверено модерацией
Модерация