В этом руководстве вы узнаете о необязательном операторе цепочки( ?.
) в JavaScript, который упрощает способ доступа к значениям через связанные объекты.
Необязательный оператор цепочки( ?.
) позволяет получить доступ к значению свойства, расположенного глубоко внутри цепочки объектов, без явной проверки того, является ли каждая ссылка в цепочке null
или undefined
.
Если одна из ссылок в цепочке null
или undefined
, необязательный оператор цепочки( ?.
) замкнется и вернет undefined
.
Предположим, у вас есть функция, которая возвращает user
объект:
function getUser(id) { if (id & lt; = 0) { return null; } // get the user from database // and return null if id does not exist // ... // if user was found, return the user return { id: id, username: 'admin', profile: { avatar: '/avatar.png', language: 'English' } } }
Следующий код использует getUser()
для доступа к профилю пользователя:
let user = getUser(1); let profile = user.profile;
Однако, если вы передадите id
, который меньше или равен нулю, или id
не существует в базе данных, getUser()
вернет значение null
.
Поэтому перед обращением к свойству avatar
нужно проверить, не является ли user
null
с помощью логического оператора AND:
let user = getUser(2); let profile = user && user.profile;
В этом примере мы подтверждаем, что user
не является null
или undefined
, прежде чем получить доступ к значению свойства user.profile
. Это предотвращает ошибку, которая могла бы возникнуть, если бы вы просто обращались к user.profile
напрямую, не проверяя сначала пользователя.
ES2020 представил необязательный оператор цепочки, обозначаемый знаком вопроса, за которым следует точка:
?.
Чтобы получить доступ к свойству объекта с помощью необязательного оператора цепочки, вы используете один из следующих способов:
objectName ?. propertyName objectName ?. [expression]
Необязательный оператор цепочки неявно проверяет, не является ли user
null
или undefined
, прежде чем пытаться получить доступ к user.profile
:
let user = getUser(2); let profile = user ?. profile;
В этом примере, если user
имеет значение null
или undefined
, необязательный оператор цепочки( ?.
) немедленно возвращает значение undefined
.
Технически это эквивалентно следующему:
let user = getUser(2); let profile =(user !== null || user !== undefined) ? user.profile : undefined;
Стекирование
В случае, если user
объект, возвращаемый getUser()
, не имеет свойства profile
. Попытка получить доступ к avatar
без предварительной проверки user.profile
приведет к ошибке.
Чтобы избежать ошибки, вы можете использовать необязательный оператор цепочки несколько раз, например:
let user = getUser(-1); let avatar = user ?. profile ?. avatar;
В этом случае avatar
не undefined
.
Комбинирование с нулевым оператором объединения
Если вы хотите назначить user
профиль по умолчанию, вы можете комбинировать необязательный оператор цепочки( ?.
) с нулевым оператором объединения( ??
) следующим образом:
let defaultProfile = { default: '/default.png', language: 'English'}; let user = getUser(2); let profile = user ?. profile ?? defaultProfile;
В этом примере, если user.profile
имеет значение null
или undefined
, профиль примет значение defaultProfile
из-за нулевого оператора объединения.
Использование с вызовами функций
Предположим, что у вас есть следующий файловый API:
let file = { read() { return 'file content'; }, write(content) { console.log(`Writing $ { content } to file...`); return true; } };
В этом примере вызывается метод read()
объекта file
:
let data = file.read(); console.log(data);
Если вы вызываете метод, который не существует в file
объекте, вы получите TypeError
:
let compressedData = file.compress();
Ошибка:
Uncaught TypeError: file.compress is not a function
Однако, если вы используете необязательный оператор цепочки с вызовом метода, выражение вернет undefined
значение, а не выдаст ошибку:
let compressedData = file.compress?.();
compressedData
теперь undefined
.
Это полезно, когда вы используете API, в котором метод может быть недоступен по какой-либо причине, например, для определенного браузера или устройства.
Ниже показан синтаксис использования необязательного оператора цепочки с вызовом функции или метода:
functionName ?.(args)
Необязательный оператор цепочки( ?.
) также полезен, если у вас есть функция с необязательным обратным вызовом:
function getUser(id, callback) { // get user // ... let user = { id: id, username: 'admin' }; // test if the callback exists if (callback) { callback(user); } return user; }
Используя необязательный оператор цепочки, вы можете пропустить тест, если обратный вызов существует:
function getUser(id, callback) { // get user // ... let user = { id: id, username: 'admin' }; // test if the callback exists callback ? . (user); return user; }
Заключение
- Необязательный оператор цепочки(
?.
) возвращаетundefined
вместо того, чтобы выдавать ошибку, если вы пытаетесь получить доступ к свойствуnull
илиundefined
объекта:obj ?. property
. - Объедините необязательный оператор цепочки(
?.
) с нулевым оператором объединения(??
), чтобы назначить значение по умолчанию. - Используйте
functionName ?.(args)
, чтобы избежать явной проверки, не является лиfunctionName
undefined
илиnull
перед его вызовом.