Optional chaining (?.) и nullish coalescing (??) в JavaScript: понятное руководство с...

Optional chaining (?.) и nullish coalescing (??) в JavaScript: понятное руководство с примерами

Optional chaining (?.) и nullish coalescing (??) в JavaScript: понятное руководство с примерами

Запросы вроде «optional chaining в JavaScript» или «оператор ?? что делает» стабильно в топе у начинающих. И не зря: пара операторов ?. и ?? делает код короче, безопаснее и понятнее. В этом руководстве вы узнаете, когда и как их применять, чего избегать и как комбинировать для максимальной пользы.

Что такое optional chaining (?.)

Optional chaining безопасно обращается к вложенным свойствам и методам: если на любом шаге встречается null или undefined, выражение возвращает undefined вместо падения с ошибкой.

const user = { profile: { name: "Анна" } };

// Безопасный доступ
const city = user?.profile?.address?.city; // undefined, но без ошибки

// Обычный доступ (может бросить TypeError, если profile или address отсутствуют)
// const city = user.profile.address.city;

Важно: ставьте ?. на каждом потенциально «дырявом» шаге. В user?.profile.address.city отработает только первая проверка; если profile есть, но address нет — будет ошибка.

Варианты синтаксиса

  • Доступ к свойству: obj?.prop
  • Доступ по индексу/ключу: obj?.[key]
  • Вызов метода: obj.method?.(args) — вызовится только если method существует и не равен null/undefined
  • const api = {
      utils: {
        pick(obj, key) { return obj?.[key]; }
      }
    };
    
    // Вызов метода, если он есть
    const result = api.utils.pick?.({ a: 1 }, "a"); // 1
    
    // Безопасное чтение индекса
    const first = [10, 20]?.[0]; // 10
    

    Что такое nullish coalescing (??)

    Оператор ?? возвращает правую часть, только если левая — null или undefined. В отличие от ||, он не считает 0, пустую строку "" или false поводом подставлять значение по умолчанию.

    const count = 0;
    
    const a = count || 10; // 10 (не то, что мы хотели)
    const b = count ?? 10; // 0 (корректно, т.к. 0 — валидное значение)
    
    const title = "";
    const t1 = title || "Заголовок"; // "Заголовок"
    const t2 = title ?? "Заголовок"; // "" (оставляем пустую строку как осознанный выбор)
    

    Комбинируем ?. и ??

    Частый паттерн — безопасный доступ с разумным дефолтом.

    // Если у пользователя нет аватара — используем заглушку
    function getAvatarUrl(user) {
      return user?.profile?.avatar ?? "/img/default-avatar.png";
    }
    
    // Безопасная длина массива
    const len = response?.items?.length ?? 0;
    

    Реальные кейсы из практики

    1) Чтение глубоких полей ответа API

    const resp = await getData();
    const total = resp?.meta?.pagination?.total ?? 0;
    const items = resp?.data ?? [];
    

    2) Опциональные колбэки

    function save(data, callbacks = {}) {
      // Вызовем, только если onStart задан
      callbacks.onStart?.();
    
      // ... сохраняем
    
      // Вызовем, только если onSuccess задан
      callbacks.onSuccess?.(data);
    }
    

    3) Безопасная работа с DOM

    const titleEl = document.querySelector(".title");
    
    // Установим текст, если элемент найден
    if (titleEl?.textContent !== undefined) {
      titleEl.textContent = "Привет, мир!";
    }
    

    Частые ошибки и как их избежать

    1. Ставите только один ?., а вложенности больше.
      Решение: на каждом потенциально пустом шаге используйте ?..

      // Плохо
      user?.profile.address.city;
      
      // Хорошо
      user?.profile?.address?.city;
      
    2. Путаете ?? и ||. || «съедает» 0, false и пустую строку, ?? — нет.

      const limit = config.limit ?? 20; // 0 остаётся 0
      
    3. Проверяете существование значений через if (obj?.prop). Такой тест упадёт для валидных «ложных» значений (0, false, «»). Лучше явно сравнить с null/undefined.

      // Вместо так:
      if (user?.age) {
        // 0 лет — тоже возраст, но условие не выполнится
      }
      
      // Делайте так:
      if (user?.age ?? null) {
        // значение существует (можно дополнительно проверить тип)
      }
      
    4. Вызов не-функции через ?.(). obj.method?.() пропустит вызов, если method null/undefined. Но если method есть, однако это не функция — получите TypeError. Проверяйте тип при необходимости.

    5. Небезопасные выражения после ?. ESLint-правило no-unsafe-optional-chaining помогает ловить ошибки, когда после ?. идёт операция, предполагающая, что значение точно не undefined.

    Лучшие практики

  • Ставьте ?. там, где данные действительно могут отсутствовать (ответ API, опциональный конфиг, пользовательский ввод).
  • Используйте ?? для дефолтов, когда только null/undefined означают «нет значения». Для всего остального — сознательные 0, false, «» — дефолт не нужен.
  • Комбинируйте ?. и ?? в одну линию, чтобы упростить защитный код.
  • Не увлекайтесь: избыточные ?. там, где структура гарантирована, замедляют чтение кода.
  • Продвинутые трюки

    // Удаление свойства, если объект существует
    const ok = delete settings?.temp;
    
    // Доступ к длине только если это строка или массив
    const len = (Array.isArray(x) || typeof x === "string") ? x.length : undefined;
    // С короткой записью и дефолтом
    const safeLen = x?.length ?? 0; // осторожно: у объектов без length будет undefined
    

    Поддержка и транспиляция

    Операторы ?. и ?? поддерживаются современными браузерами и Node.js. Для старых окружений используйте Babel/TypeScript — плагины давно стабильны. Не существует «полифилла» в чистом виде (это синтаксис), поэтому нужен транспайлер на этапе сборки.

    Итоги

    Optional chaining и nullish coalescing — быстрый способ сделать код безопаснее к «дырявым» данным и аккуратно расставить значения по умолчанию. Освойте их комбинации, следите за ловушками (|| против ??, достаточное количество ?.) — и ваш базовый JavaScript станет заметно чище.

    Хотите системно прокачать основы и перейти к практическим проектам? Загляните в курс: Прокачать навыки в курсе «JavaScript с Нуля до Гуру 2.0» — пошаговая практика, разбор типичных ошибок и личные мини‑проекты.

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий