Learn JavaScript

?? - оператор нулевого слияния для значений по умолчанию в JavaScript

?? - это оператор нулевого слияния (nullish coalescing), который подставляет значение справа только если слева null или undefined.

Он особенно полезен для значений по умолчанию, когда 0, false и пустая строка считаются нормальными и не должны заменяться.

Название может немного сбивать с толку: оператор не связан с числом 0. Здесь речь именно про значения null и undefined.

Синтаксис

left ?? right

Если left равен null или undefined, результатом будет right.

Во всех остальных случаях результатом будет left.

Что делает ??

Оператор проверяет левую часть только на null и undefined.

console.log(null ?? "default");      // "default"
console.log(undefined ?? "default"); // "default"
console.log("text" ?? "default");    // "text"

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

Что возвращает ??

?? не приводит результат к boolean. Он возвращает одно из исходных значений.

const value = 0 ?? 10;

console.log(value);        // 0
console.log(typeof value); // "number"

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

null и undefined

Это два случая, для которых ?? действительно срабатывает.

console.log(null ?? "Guest");      // "Guest"
console.log(undefined ?? "Guest"); // "Guest"

Если значение пришло как null или undefined, оператор подставит запасной вариант справа.

0, false и пустая строка

Это ключевое отличие ?? от ||.

console.log(0 ?? 10);       // 0
console.log(false ?? true); // false
console.log("" ?? "text");  // ""

Хотя эти значения являются falsy, они не считаются отсутствующими значениями, поэтому ?? их не заменяет.

NaN тоже не считается отсутствующим значением

Это ещё один важный нюанс:

console.log(NaN ?? 5); // NaN

NaN - это специальное числовое значение, но не null и не undefined.

Если нужно отдельно обрабатывать NaN, используют Number.isNaN().

?? и ||

Эти операторы часто путают, потому что оба могут подставлять значение по умолчанию.

const page = 0;

console.log(page || 1); // 1
console.log(page ?? 1); // 0

|| подставляет значение справа для любого falsy-значения:

  • 0
  • false
  • ""
  • NaN
  • null
  • undefined

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

  • null
  • undefined

Поэтому, если 0 и "" валидны, чаще лучше использовать именно ??.

?? и оператор опциональной цепочки

Очень часто ?? используют вместе с ?..

const user = {};

const city = user.profile?.address?.city ?? "Город не указан";

console.log(city); // "Город не указан"

Такой шаблон очень удобен:

  • ?. безопасно читает значение
  • ?? подставляет дефолт, если результат оказался null или undefined

Цепочка из нескольких ??

Оператор можно использовать несколько раз подряд.

console.log(null ?? undefined ?? "default"); // "default"

JavaScript будет брать первое значение, которое не равно null и не равно undefined.

Короткое замыкание

?? работает с коротким замыканием.

Если левое значение уже подходит, правая часть не вычисляется.

const name = "Sam";

console.log(name ?? "Guest"); // "Sam"

Правая часть здесь уже не нужна.

Когда это полезно

?? удобно использовать, когда:

  • нужно подставить значение по умолчанию только для null и undefined
  • 0, false и "" являются нормальными значениями
  • данные приходят из формы, API, localStorage или настроек
  • код читается лучше через явную проверку на null и undefined, чем через общий falsy-подход

Пример:

function getPage(page) {
  return page ?? 1;
}

console.log(getPage(0));         // 0
console.log(getPage(undefined)); // 1

Ограничение: нельзя смешивать с || и && без скобок

Это важное синтаксическое правило.

Так писать нельзя:

// null || undefined ?? "x"; // SyntaxError
// true && undefined ?? "x"; // SyntaxError

Нужно явно расставить скобки:

console.log((null || undefined) ?? "x"); // "x"
console.log(true && (undefined ?? "x")); // "x"

JavaScript специально требует скобки, чтобы не было путаницы в чтении выражения.

?? не работает с необъявленной переменной

Если переменная вообще не объявлена, ошибка произойдёт раньше.

// notDeclared ?? "x"; // ReferenceError

Оператор помогает только тогда, когда значение уже существует как переменная, но может быть null или undefined.

Частые ошибки

Использовать || там, где нужен ??

const count = 0;

console.log(count || 10); // 10
console.log(count ?? 10); // 0

Если 0 - допустимое значение, || даст неверный дефолт.

Думать, что ?? реагирует на все falsy-значения

console.log("" ?? "text");   // ""
console.log(false ?? true);  // false
console.log(NaN ?? 5);       // NaN

Оператор проверяет только null и undefined.

Смешивать ?? с || или && без скобок

// null || undefined ?? "x"; // SyntaxError

Нужны явные скобки.

Ожидать, что ?? спасёт от необъявленной переменной

// notDeclared ?? "x"; // ReferenceError

Если переменная не существует, ошибка будет раньше.

Быстрая памятка

  • left ?? right возвращает right только если left равен null или undefined
  • 0, false, "" и NaN не считаются отсутствующими значениями
  • ?? часто удобнее ||, когда falsy-значения допустимы
  • оператор возвращает одно из исходных значений без преобразования в boolean
  • ?? очень часто используют вместе с ?.
  • ?? нельзя смешивать с && и || без скобок

Коротко

?? - это оператор JavaScript для подстановки значения по умолчанию только в случаях null и undefined. Главное, что стоит запомнить: он не заменяет 0, false и пустую строку, поэтому во многих прикладных сценариях подходит лучше, чем ||, особенно рядом с ?..