Оператор опциональной последовательности
Оператор опциональной последовательности ?.
позволяет получить значение свойства, находящегося на любом уровне вложенности в цепочке связанных между собой объектов, без необходимости проверять каждое из промежуточных свойств в ней на существование. ?.
работает подобно оператору .
, за исключением того, что не выбрасывает исключение, если объект, к свойству или методу которого идёт обращение, равен null
или undefined
. В этих случаях он возвращает undefined
.
Таким образом, мы получаем более короткий и понятный код при обращении к вложенным по цепочке свойствам объекта, когда есть вероятность, что какое-то из них отсутствует.
Интерактивный пример
Синтаксис
obj?.prop;
obj?.[expr];
arr?.[index];
func?.(args);
Описание
Оператор опциональной последовательности предоставляет способ упростить доступ к значениям в цепочке объектов, когда возможно, что какое-то свойство (или метод) в ней равно undefined
или null
.
Для примера, создадим объект obj
, имеющий вложенную структуру. Без оператора опциональной последовательности поиск глубоко расположенных подсвойств требует проверки всех промежуточных свойств на существование, например:
let nestedProp = obj.first && obj.first.second;
Если обращаться к obj.first.second
без проверки obj.first
, то, если свойство obj.first
равно null
или undefined
, выбросится исключение TypeError
.
Однако, с оператором опциональной последовательности (?.
) не требуется явно проверять ссылку на obj.first
перед обращением к obj.first.second
:
let nestedProp = obj.first?.second;
Если используется оператор ?.
вместо .
, JavaScript знает о необходимости проверки obj.first
перед обращением к obj.first.second
. Если значение obj.first
равно null
или undefined
, выполнение выражения автоматически прекращается и возвращается undefined
.
Это эквивалентно следующему (кроме создания временной переменной):
let temp = obj.first;
let nestedProp = temp === null || temp === undefined ? undefined : temp.second;
Опциональная последовательность с вызовом функции
Вы можете использовать ?.
, когда необходимо вызвать метод, которого может не существовать. Это может быть полезно, например, при использовании API, в котором метод может быть недоступен из-за устаревания или не поддерживаемости устройством пользователя.
Использование ?.
с вызовом функции значит, что выполнение автоматически вернёт undefined
, а не выбросит исключение, если метод не найден:
let result = someInterface.customMethod?.();
Примечание: Для существующего свойства, не являющегося функцией, использование конструкции x.y?.()
всё равно выбросит TypeError
исключение (x.y не является функцией
).
Работа с колбэк-функциями и обработчиками событий
Если вы используете колбэк-функции или извлекаете методы объекта деструктурирующим присваиванием, Вы можете получить несуществующие значения, которые нельзя вызывать как функции до проверки на их существование. Используя оператор ?.
, вы можете избежать лишних проверок:
// С использованием ES2019
function doSomething(onContent, onError) {
try {
// ... делаем что-то с данными
} catch (err) {
if (onError) {
// проверяем, существует ли onError
onError(err.message);
}
}
}
// С использованием оператора опциональной последовательности
function doSomething(onContent, onError) {
try {
// ... делаем что-то с данными
} catch (err) {
onError?.(err.message); // не выбросит исключение, если onError равен undefined
}
}
Опциональные последовательности в выражениях
Вы также можете использовать оператор опциональной последовательности, когда обращаетесь к свойству с помощью скобочной нотации:
let nestedProp = obj?.["prop" + "Name"];
Примеры
Базовый пример
В этом примере производится обращение к свойству name
элемента с ключом bar
объекта Map
. Элемент с таким ключом отсутствует, но исключение выброшено не будет; nameBar
равен 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, т.к. x не был инкрементирован
Совместное использование операторов опциональной последовательности
Во вложенных объектах возможно использование оператора опциональной последовательности неограниченное количество раз:
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls", // точный адрес неизвестен
},
};
let customerCity = customer.details?.address?.city;
// … это также работает с вызовами функций
let duration = vacations.trip?.getTime?.();
Использование с оператором ??
Оператор ?? может использоваться после опциональной последовательности для установления значения по умолчанию:
let customer = {
name: "Carl",
details: { age: 82 },
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
Спецификации
Specification |
---|
ECMAScript Language Specification # prod-OptionalExpression |
Совместимость с браузерами
BCD tables only load in the browser