Русский

Освойте оператор нулевого слияния (??) в JavaScript для чистого присвоения значений по умолчанию. Узнайте отличия от оператора ИЛИ (||) и рассмотрите примеры.

Оператор нулевого слияния (Nullish Coalescing) в JavaScript: Подробное руководство по присвоению значений по умолчанию

В JavaScript присвоение значений по умолчанию является обычной задачей. Традиционно разработчики использовали для этого оператор ИЛИ (||). Однако оператор нулевого слияния (??), введенный в ECMAScript 2020, предоставляет более точный и надежный способ обработки присвоений значений по умолчанию, особенно при работе со значениями null или undefined. Это руководство подробно описывает оператор нулевого слияния, исследуя его синтаксис, поведение, отличия от оператора ИЛИ и практические варианты использования.

Что такое нулевое слияние?

Оператор нулевого слияния (??) — это логический оператор, который возвращает свой правый операнд, когда его левый операнд равен null или undefined. В противном случае он возвращает свой левый операнд. Проще говоря, он предоставляет значение по умолчанию только тогда, когда переменная строго равна null или undefined.

Синтаксис

Синтаксис оператора нулевого слияния прост:

leftOperand ?? rightOperand

Здесь leftOperand — это переменная или выражение, которое вы хотите проверить на null или undefined, а rightOperand — это значение по умолчанию, которое вы хотите присвоить, если leftOperand действительно равно null или undefined.

Пример

Рассмотрим следующий пример:

const username = null ?? "Guest";
console.log(username); // Вывод: Guest

const age = undefined ?? 25;
console.log(age); // Вывод: 25

const city = "London" ?? "Unknown";
console.log(city); // Вывод: London

В этом примере username присваивается значение по умолчанию "Guest", потому что оно изначально null. Аналогично, age присваивается 25, потому что оно начинается как undefined. Однако city сохраняет свое исходное значение, "London", потому что оно не является ни null, ни undefined.

Нулевые (Nullish) против ложных (Falsy) значений

Крайне важно понимать разницу между нулевыми (nullish) и ложными (falsy) значениями в JavaScript. Нулевое значение — это либо null, либо undefined. Ложное значение — это значение, которое считается ложным при встрече в булевом контексте. Ложные значения включают:

Ключевое отличие заключается в том, что оператор нулевого слияния проверяет только null или undefined, тогда как оператор ИЛИ (||) проверяет любое ложное значение.

Разница между ?? и ||

Оператор ИЛИ (||) — это логический оператор ИЛИ, который возвращает правый операнд, если левый операнд является ложным. Хотя его можно использовать для присвоения значений по умолчанию, он может привести к неожиданному поведению при работе со значениями, такими как 0 или пустая строка.

Пример: Недостатки ||

const quantity = 0 || 10; // Мы хотим, чтобы по умолчанию было 10, если quantity отсутствует
console.log(quantity); // Вывод: 10 (Неожиданно!) потому что 0 является ложным

const text = '' || 'Default Text'; //Мы хотим, чтобы по умолчанию был текст, если text отсутствует
console.log(text); // Вывод: Default Text (Неожиданно!) потому что '' является ложным

В первом примере мы предполагали присвоить значение по умолчанию 10 только в том случае, если quantity отсутствовало (null или undefined). Однако, поскольку 0 является ложным значением, оператор ИЛИ некорректно присвоил значение по умолчанию. Аналогично, пустая строка приводит к тому, что отображается текст по умолчанию, даже если строка существует (но пуста).

Использование ?? для точности

Перепишем предыдущий пример, используя оператор нулевого слияния:

const quantity = 0 ?? 10;
console.log(quantity); // Вывод: 0 (Корректно!)

const text = '' ?? 'Default Text';
console.log(text); // Вывод: '' (Корректно!)

Теперь вывод соответствует ожиданиям. Оператор нулевого слияния проверяет только null или undefined, поэтому 0 и '' рассматриваются как допустимые значения, и их исходные значения сохраняются.

Варианты использования нулевого слияния

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

1. Обработка необязательных параметров функции

При определении функции с необязательными параметрами вы можете использовать оператор нулевого слияния для предоставления значений по умолчанию, если параметры не предоставлены.

function greet(name, greeting) {
  const userName = name ?? "User";
  const userGreeting = greeting ?? "Hello";
  console.log(`${userGreeting}, ${userName}!`);
}

greet(); // Вывод: Hello, User!
greet("Alice"); // Вывод: Hello, Alice!
greet("Bob", "Greetings"); // Вывод: Greetings, Bob!

2. Установка параметров конфигурации по умолчанию

При работе с объектами конфигурации вы можете использовать оператор нулевого слияния, чтобы гарантировать использование значений по умолчанию, если некоторые параметры конфигурации не указаны.

const config = {
  timeout: 5000,
  retries: 3
};

function fetchData(options) {
  const timeout = options.timeout ?? 10000; // Таймаут по умолчанию 10 секунд
  const retries = options.retries ?? 5; // По умолчанию 5 повторных попыток
  console.log(`Timeout: ${timeout}, Retries: ${retries}`);
}

fetchData(config); // Вывод: Timeout: 5000, Retries: 3
fetchData({}); // Вывод: Timeout: 10000, Retries: 5
fetchData({timeout:null, retries: undefined}); // Вывод: Timeout: 10000, Retries: 5

3. Доступ к вложенным свойствам объекта

При доступе к свойствам вложенных объектов оператор нулевого слияния может быть объединен с опциональной цепочкой (?.) для предоставления значений по умолчанию, если какие-либо из промежуточных свойств равны null или undefined.

const user = {
  profile: {
    address: {
      city: "New York"
    }
  }
};

const cityName = user?.profile?.address?.city ?? "Unknown";
console.log(cityName); // Вывод: New York

const unknownUser = {};
const unknownCityName = unknownUser?.profile?.address?.city ?? "Unknown";
console.log(unknownCityName); // Вывод: Unknown

4. Работа с API и внешними данными

При получении данных из API или внешних источников оператор нулевого слияния может использоваться для предоставления значений по умолчанию, если некоторые поля данных отсутствуют или имеют значения null или undefined. Рассмотрим получение данных пользователя из разных регионов. Предположим, что некоторые регионы могут не включать поле country в данные пользователя.

async function getUserData(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const data = await response.json();
    const country = data.country ?? "Unknown Country";
    const timezone = data.timezone ?? "UTC";
    console.log(`User is from: ${country}, Timezone: ${timezone}`);
  } catch (error) {
    console.error("Error fetching user data:", error);
  }
}

// Симуляция различных ответов API:
const userWithCountry = { name: "John", country: "USA", timezone: "EST" };
const userWithoutCountry = { name: "Jane", timezone: "GMT" };

// Для тестирования этого потребуется реальный API или имитация fetch.
// В демонстрационных целях, давайте сымитируем ответы:
global.fetch = async (url) => {
    if (url.includes("123")) {
        return { json: async () => userWithCountry };
    } else if (url.includes("456")) {
        return { json: async () => userWithoutCountry };
    }
    throw new Error("Unexpected URL");
};

getUserData(123); // Вывод: Пользователь из: USA, Часовой пояс: EST
getUserData(456); // Вывод: Пользователь из: Неизвестная страна, Часовой пояс: GMT

Приоритет операторов

Оператор нулевого слияния имеет относительно низкий приоритет. Он ниже, чем операторы ИЛИ (||) и И (&&). Поэтому при объединении оператора нулевого слияния с другими логическими операторами важно использовать скобки, чтобы явно определить порядок выполнения операций. Отсутствие скобок может привести к синтаксическим ошибкам или неожиданному поведению.

Пример: Использование скобок для ясности

// Без скобок (SyntaxError)
// const result = false || null ?? "Default"; // SyntaxError: Неожиданный токен '??'

// Со скобками (Корректно)
const result = false || (null ?? "Default");
console.log(result); // Вывод: Default

const anotherResult = (false || null) ?? "Default";
console.log(anotherResult); // Вывод: null

В первом примере отсутствие скобок приводит к SyntaxError, потому что движок JavaScript не может определить предполагаемый порядок операций. Добавляя скобки, мы явно указываем движку сначала вычислить оператор нулевого слияния. Второй пример действителен; однако вывод отличается, потому что выражение || вычисляется первым.

Совместимость с браузерами

Оператор нулевого слияния (??) является относительно новой функцией, поэтому крайне важно учитывать совместимость с браузерами, особенно если вы ориентируетесь на старые браузеры. Большинство современных браузеров поддерживают оператор нулевого слияния, включая:

Если вам необходимо поддерживать старые браузеры, вы можете использовать транспилятор, такой как Babel, для преобразования вашего кода в совместимую версию JavaScript. Babel преобразует оператор ?? в эквивалентный код JavaScript, который работает в старых средах.

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

Вот несколько лучших практик для эффективного использования оператора нулевого слияния:

Глобальные аспекты

При разработке для глобальной аудитории учитывайте следующие моменты, связанные с присвоением значений по умолчанию:

Пример: Локализация с использованием нулевого слияния

Предположим, вы хотите отобразить сообщение приветствия по умолчанию на разных языках в зависимости от локали пользователя. Вы можете использовать оператор нулевого слияния, чтобы предоставить сообщение по умолчанию, если локализованное сообщение недоступно.

function getWelcomeMessage(locale) {
  const localizedMessages = {
    en: "Welcome!",
    fr: "Bienvenue !",
    de: "Willkommen!"
  };

  const message = localizedMessages[locale] ?? "Welcome!"; // По умолчанию английский, если локаль не найдена
  return message;
}

console.log(getWelcomeMessage("fr")); // Вывод: Bienvenue !
console.log(getWelcomeMessage("es")); // Вывод: Welcome! (По умолчанию английский)

Заключение

Оператор нулевого слияния (??) является ценным дополнением к языку JavaScript. Он предоставляет более точный и надежный способ присвоения значений по умолчанию по сравнению с оператором ИЛИ (||), особенно при работе со значениями, такими как 0 или пустые строки. Понимая его синтаксис, поведение и варианты использования, вы можете писать более чистый и поддерживаемый код, который точно обрабатывает присвоения значений по умолчанию. Не забывайте учитывать совместимость с браузерами, приоритет операторов и глобальные аспекты при использовании оператора нулевого слияния в своих проектах.

Следуя лучшим практикам, изложенным в этом руководстве, вы сможете эффективно использовать оператор нулевого слияния для повышения качества и надежности вашего кода JavaScript, делая его более надежным и легким для понимания. Всегда помните о приоритете ясности и удобства сопровождения в вашем коде, и оператор нулевого слияния может стать мощным инструментом для достижения этих целей.