Оператор опциональной последовательности

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

Оператор опциональной последовательности ?. позволяет получить значение свойства обьекта размещенного глубоко по цепочке включенных обьектов без необходимости проверять каждую ссылку в цепочке на существование.  ?. оператор действует подобно до оператора ., в отличии от того, что не может получить ошибку в ссылке на null или undefined, в этих случаях он вернет undefined. Когда используется для вызова функций - тоже возвращает undefined если функция не существует.

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

Warning! As of August 2019, no environment natively implements this feature. If you use Babel, you may use this plugin to emulate optional chaining.

Синтаксис

obj?.prop
obj?.[expr]
func?.(args)

Описание

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

Для примера, создадим обьект obj который имеет в своей структуре вложенность. Без оператора опциональной последовательности поиск глубоко расположенных "подсвойств" обязует нас проверить все промежуточные ссылки, как тут:

let nestedProp = obj.first && obj.first.second;

Значение из obj.first проверяется на не-null (и не-undefined) перед доступом к значению obj.first.second. Это предупреждает ошибку которая могла случитьсяесли мы упростим выражение до obj.first.second непосредственно, без проверки значения obj.first.

С оператором опциональной последовательности (?.), мы не обязаны явно проверять промежуточные звенья как obj.first перед попыткой доступа к obj.first.second:

let nestedProp = obj.first?.second;

Используя ?. оператор вместо ., JavaScript знает об необходимости проверки obj.first на null или undefined значения, перед предоставлением доступа к obj.first.second. Если obj.first равно null или undefined, выполнение выражения автоматически прекращается и возвращается undefined.

Это еквивалентно следующему:

let nestedProp = (obj.first == null ? undefined : obj.first.second);

Опциональная последовательность с вызовом функции

Вы можете использовать оператор опциональной последовательности когда пытаетесь вызвать метод которого может не существовать. Это может быть полезно, например, когда используете API в котором метод может быть не доступен более, ссылаясь на дату реализации или потому, что данный метод не доступен на устройстве пользователя.

Использование оператор опциональной последовательности с вызовом функции значит, что выполнение автоматически вернет undefined, а не выбросит исключение если метод не найден:

let result = someInterface.customMethod?.();

Note: If there is a property with such a name and which is not a function, using ?. will still raise a TypeError exception (x.y is not a function).

Работа с опциональними колбек функциями и обработчиками событий

Если вы используете колбек функции или fetch методы с обьекта с a destructuring assignment, Вы  можете получить не существующее значение которое Вы не сможете вызвать как функцию пока не проверите ее существование. Использовав ?., Вы можете избежать этих излишних проверок:

// Written as of ES2019
function doSomething(onContent, onError) {
  try {
    // ... do something with the data 
  }
  catch (err) {
    if (onError) { // Testing if onError really exists
      onError(err.message);
    }
  }
}
// Using optional chaining with function calls
function doSomething(onContent, onError) {
  try {
   // ... do something with the data
  }
  catch (err) {
    onError?.(err.message); // no exception if onError is undefined
  }
}

Опциональные последовательности в выражениях

Вы также можете использовать оператор опциональной последовательностиo когда получаете доступ к свойству используя доступ по имени свойства обьекта:

let nestedProp = obj?.['prop' + 'Name'];

Примеры

Базовый пример

В этом примере найдем значения свойства "name" для свойства bar в карте, когда в ней данного свойства в ней нет. Результатом здесь будет undefined.

let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});

let nameBar = myMap.get("bar")?.name;

Сокращенное выполнение

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

let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];

console.log(x); // 0 as x was not incremented

Совмесное использование с оператором опциональной последовательности

В вложенных структурах, возможно использование оператора опциональной последовательности несколько раз:

let customer = {
  name: "Carl",
  details: {
    age: 82,
    location: "Paradise Falls" // detailed address is unknown
  }
};
let customerCity = customer.details?.address?.city;

// … this also works with optional chaining function call
let duration = vacations.trip?.getTime?.();

Спецификации

Specification Status Comment
Proposal for the "optional chaining" operator Stage 3

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

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung InternetNode.js
Optional chaining operator (?.)
Экспериментальная
Chrome Полная поддержка 79
Отключено
Полная поддержка 79
Отключено
Отключено From version 79: this feature is behind the Experimental JavaScript preference (needs to be set to true). To change preferences in Chrome, visit chrome://flags.
Edge Нет поддержки НетFirefox Нет поддержки НетIE Нет поддержки НетOpera Полная поддержка 65
Отключено
Полная поддержка 65
Отключено
Отключено From version 65: this feature is behind the Experimental JavaScript preference (needs to be set to true).
Safari Нет поддержки НетWebView Android Нет поддержки НетChrome Android Полная поддержка 79
Отключено
Полная поддержка 79
Отключено
Отключено From version 79: this feature is behind the Experimental JavaScript preference (needs to be set to true). To change preferences in Chrome, visit chrome://flags.
Firefox Android Нет поддержки НетOpera Android Нет поддержки НетSafari iOS Нет поддержки НетSamsung Internet Android Нет поддержки Нетnodejs Нет поддержки Нет

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Экспериментальная. Ожидаемое поведение может измениться в будущем.
Экспериментальная. Ожидаемое поведение может измениться в будущем.
Пользователь должен сам включить эту возможность.
Пользователь должен сам включить эту возможность.

Смотрите также