У вас включен AdBlock или иной блокировщик рекламы.

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

Спасибо за понимание.

В другой раз
DevGang блог о програмировании
Авторизоваться

Введение в optional chaining operator 

Длинные цепочки доступа к свойствам в JavaScript могут быть подвержены ошибкам, так как любой из них может иметь значение null или undefined (также известный как «нулевые» значения). Проверка существования свойства на каждом шаге легко превращается в глубоко вложенную структуру if-statements или длинное условие в if, реплицирующее цепочку доступа к свойству:

const nameLength = db.user.name.length;
let nameLength;

if (db && db.user && db.user.name)
 nameLength = db.user.name.length;

Вышесказанное также можно выразить с помощью тернарного оператора, который не совсем помогает читабельности:

const nameLength =
 (db
   ? (db.user
     ? (db.user.name
       ? db.user.name.length
       : undefined)
     : undefined)
   : undefined);

Представляем опциональный оператор цепочки

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

Используя новый необязательный оператор связывания, мы можем переписать приведенный выше пример следующим образом:

const nameLength = db?.user?.name?.length;

Что происходит , когда db, user или name равны undefined или null? С новым опциональным оператором цепочек, JavaScript инициализирует nameLength как undefined вместо того , чтобы бросать ошибку.

Обратите внимание, что это поведение также более надежно, чем наша проверка if (db && db.user && db.user.name). Например, что, если name гарантированно будет строкой? Мы могли бы изменить name?.length на name.length. Тогда, если бы в name была пустая строка, мы все равно получили бы правильную длину 0. Это потому, что пустая строка является ложным значением: она ведет себя как false в условиях if. Необязательный оператор цепочки исправляет этот распространенный источник ошибок.

Дополнительные синтаксические формы: вызовы и динамические свойства

Также есть версия оператора для вызова дополнительных методов:

const adminOption = db?.user?.validateAdminAndGetPrefs?.().option;

Синтаксис может показаться неожиданным, так как ?.() это фактический оператор, который применяется к выражению перед ним.

Существует третье использование оператора, а именно необязательный динамический доступ к свойству, который осуществляется через ?.[]. Он либо возвращает значение, на которое ссылается аргумент в скобках, либо, undefined если нет объекта для получения значения. Вот возможный вариант использования, следуя примеру выше:

const optionName = 'optional setting';
const optionLength = db?.user?.preferences?.[optionName].length;

Эта последняя форма также доступна для необязательного индексирования массивов, например:

const userIndex = 42;
const userName = usersArray?.[userIndex].name;

Необязательный оператор связывания ?? может быть объединен с нулевым оператором объединения, когда требуется undefined значение не по умолчанию. Это обеспечивает безопасный глубокий доступ к свойству с указанным значением по умолчанию, обращаясь к общему варианту _.get использования, который ранее требовал пользовательских библиотек, таких как lodash:

const object = { id: 123, names: { first: 'Alice', last: 'Smith' }};

{ // lodash:
 const firstName = _.get(object, 'names.first');
 // → 'Alice' const middleName = _.get(object, 'names.middle', '(no middle name)');
 // → '(no middle name)'
}

{ // с новым оператором:
 const firstName = object?.names?.first ?? '(no first name)';
 // → 'Alice' const middleName = object?.names?.middle ?? '(no middle name)';
 // → '(no middle name)'
}

Свойства необязательного оператора цепочки

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

Короткое замыкание означает не оценку остальной части выражения, если дополнительный оператор цепочки возвращается рано:

db?.user?.grow(++age);

Стекирование означает, что к последовательности обращений к свойствам можно применить несколько необязательных операторов сцепления:

const firstNameLength = db.users?.[42]?.names.first.length;

Тем не менее, подумайте об использовании более одного необязательного оператора цепочки в одной цепочке. Если значение гарантированно не будет нулевым, то использование оператора ?. для доступа к свойствам не рекомендуется. В приведенном выше примере, db всегда можно определить, но db.users и db.users[42] может не существовать. Если в базе данных есть такой пользователь, names.first.length предполагается, что он всегда определен.

Необязательное удаление означает, что оператор delete может быть объединен с необязательной цепочкой:

delete db?.user;

Более подробную информацию можно найти в разделе «Семантика».

#JavaScript