← Назад к вопросам

Для чего нужен оператор?

2.0 Middle🔥 122 комментариев
#JavaScript Core

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Оператор ? — различные применения

Оператор ? в JavaScript и TypeScript имеет несколько применений в зависимости от контекста. Я использую все из них в production.

1. Nullish Coalescing Operator (??)

Возвращает правый операнд если левый null или undefined:

const name = userInput ?? 'Anonymous';

// Эквивалент с ||, но лучше
const name = userInput || 'Anonymous'; // Плохо для 0, '', false

// Разница:
const count = 0;
console.log(count || 10); // 10 (неправильно!)
console.log(count ?? 10); // 0 (правильно!)

const text = '';
console.log(text || 'default'); // 'default' (неправильно!)
console.log(text ?? 'default'); // '' (правильно!)

Практическое использование:

// Параметры с дефолтными значениями
function createUser(name, email) {
  const finalName = name ?? 'Guest';
  const finalEmail = email ?? 'no-email@example.com';
  
  return { name: finalName, email: finalEmail };
}

creatеUser(null, undefined); // { name: 'Guest', email: 'no-email@example.com' }
creatеUser(0, ''); // { name: 0, email: '' }

2. Optional Chaining Operator (?.)

Безопасный доступ к свойствам (не выбросит ошибку если null/undefined):

// Плохо — может выбросить ошибку
const city = user.profile.address.city; // TypeError if user is null

// Хорошо — безопасно
const city = user?.profile?.address?.city; // undefined если любой null

Три варианта optional chaining:

// 1. Доступ к свойству
const name = user?.name;
const bio = user?.profile?.bio;

// 2. Вызов метода
const message = user?.getMessage?.();
const count = array?.length;

// 3. Доступ к элементу массива
const first = array?.[0];
const value = obj?.[dynamicKey];

Практические примеры:

// API ответ может быть неполным
const response = await fetch('/api/users/1');
const user = await response.json();

// Без optional chaining — потенциальная ошибка
const city = user.profile.address.city; // Может быть null!

// С optional chaining — безопасно
const city = user?.profile?.address?.city; // undefined

В React компонентах:

function UserProfile({ user }) {
  return (
    <div>
      {/* Без optional chaining — ошибка */}
      <p>{user.name}</p> {/* Может быть null! */}
      
      {/* С optional chaining — безопасно */}
      <p>{user?.name}</p>
      <img src={user?.profile?.avatar} />
      <button onClick={user?.getMessage?.()}>
        Send Message
      </button>
    </div>
  );
}

3. Conditional (Ternary) Operator

Условный оператор — condition ? true : false:

const status = isLoggedIn ? 'Welcome' : 'Please login';

// Вложенный
const userRole = 
  isAdmin ? 'Admin'
  : isEditor ? 'Editor'
  : 'User';

В React (очень частое использование):

function Dashboard() {
  const isLoading = true;
  const hasError = false;
  const data = null;
  
  return (
    <div>
      {isLoading ? (
        <Spinner />
      ) : hasError ? (
        <Error />
      ) : data ? (
        <Content data={data} />
      ) : (
        <Empty />
      )}
    </div>
  );
}

4. Оператор в TypeScript типах

Optional свойства:

interface User {
  id: string;        // Обязательное
  name: string;      // Обязательное
  email?: string;    // Опциональное (может быть undefined)
  phone?: string;    // Опциональное
}

const user: User = { id: '1', name: 'John' }; // OK

Union типы с null:

type Username = string | null;
type Email = string | undefined;
type Value = string | number | null | undefined;

// С strict mode нужно явно обрабатывать
const name: Username = getNullableName();
if (name !== null) {
  console.log(name.toUpperCase()); // Type-safe
}

5. Комбинирование операторов

Часто используемый паттерн:

// Получить значение или дефолт, безопасно
const city = user?.profile?.address?.city ?? 'Unknown';

// Вызвать функцию если она существует, иначе дефолт
const result = user?.getMessage?.() ?? 'No message';

// Условное отображение в React
const displayName = user?.name && user.name.length > 0 
  ? user.name 
  : 'Anonymous';

Практический пример (API обработка):

function handleUserResponse(response) {
  // Безопасно обработать неполный ответ
  const user = {
    id: response?.user?.id ?? 'unknown',
    name: response?.user?.name ?? 'Guest',
    email: response?.user?.email,
    avatar: response?.user?.profile?.avatar ?? '/default-avatar.png',
    verified: response?.user?.verified ?? false
  };
  
  // Вызвать калбэк если он есть
  response?.onSuccess?.();
  
  return user;
}

6. Разница между ?, ??, ?.

// ? — ternary (условный оператор)
const result = condition ? trueValue : falseValue;

// ?? — nullish coalescing
const value = maybeNull ?? defaultValue;

// ?. — optional chaining
const nested = obj?.property?.nested?.value;

// ?. для методов
obj?.method?.();

// ?. для индексов
array?.[0];

7. Когда я использую каждый

// Optional chaining (?.) — для безопасного доступа
const email = user?.email; // Частое использование

// Nullish coalescing (??) — для дефолтных значений
const theme = preferences?.theme ?? 'light';

// Ternary (?) — для условного отображения
return isLoading ? <Spinner /> : <Content />;

Производительность

// Optional chaining имеет небольшой overhead,
// но его незначительно

// Быстро
const a = obj.prop;

// Практически так же быстро (браузеры оптимизировали)
const b = obj?.prop;

// Всегда используй optional chaining,
// так как безопасность важнее мизерного overhead

Поддержка браузерами

  • Optional Chaining (?.) — Chrome 80+, Firefox 74+, Safari 13.1+
  • Nullish Coalescing (??) — Chrome 80+, Firefox 75+, Safari 13.1+
  • Ternary (?) — все браузеры (давно добавлено)

Для старых браузеров используй polyfills или transpilation (Babel).

Главное правило

Используй ?. когда нужен безопасный доступ к вложенным свойствам. Используй ?? когда нужно дефолтное значение для null/undefined. Используй ? : для условного отображения/вычисления.

Эти операторы делают код безопаснее и более выразительным.