Необязательная цепочка "?"
дополнительная цепочка?.
Безопасный способ доступа к свойствам вложенных объектов. Даже если свойство в середине не существует, ошибки не возникает.
Проблема «несуществующего имущества»
Если вы новичок в этом руководстве и изучаете JavaScript, вы, вероятно, не касались этой проблемы, но она довольно распространена.
Например, предположим, что у нас есть многоuser
объект, где хранятся наши пользовательские данные.
Адреса большинства наших пользователей хранятся вuser.address
, почтовый адрес хранится вuser.address.street
, но некоторые пользователи не предоставили эту информацию.
В этом случае, когда мы пытаемся получитьuser.address.street
, и пользователь не предоставляет информацию об адресе, мы получаем сообщение об ошибке:
let user = {}; // 一个没有 "address" 属性的 user 对象
alert(user.address.street); // Error!
Это ожидаемый результат. Вот как работает JavaScript. потому чтоuser.address
дляundefined
, попробуйте прочитатьuser.address.street
выйдет из строя с ошибкой.
Но во многих практических сценариях мы предпочитаемundefined
(имеется в виду нетstreet
свойство), а не ошибка.
...и еще один пример. В веб-разработке мы можем использовать специальные вызовы методов, такие какdocument.querySelector('.elem')
) получает элемент веб-страницы как объект или возвращает, если такого объекта нетnull
.
// 如果 document.querySelector('.elem') 的结果为 null,则这里不存在这个元素
let html = document.querySelector('.elem').innerHTML; // 如果 document.querySelector('.elem') 的结果为 null,则会出现错误
Аналогично, если элемент не существует, доступnull
из.innerHTML
возникает ошибка. В некоторых случаях, когда отсутствие элемента допустимо, мы хотим избежать этой ошибки и вместо этого принятьhtml = null
как результат.
Как мы этого добиваемся?
Вероятно, первое решение, которое приходит на ум, это использоватьif
или условный оператор?
Проверьте значение следующим образом:
let user = {};
alert(user.address ? user.address.street : undefined);
Это работает, и здесь нет ошибок... но недостаточно элегантно. как вы видете,"user.address"
встречается в коде дважды. Для более глубоко вложенных свойств будет больше повторений этого, и это проблема.
Например, попробуем получитьuser.address.street.name
.
нам нужно проверитьuser.address
, опять надо проверитьuser.address.street
:
let user = {}; // user 没有 address 属性
alert(user.address ? user.address.street ? user.address.street.name : null : null);
Это слишком много чепухи, и это может привести к написанию кода, который будет трудно понять другим.
Даже мы можем игнорировать эту проблему на данный момент, потому что у нас есть лучший способ сделать это, а именно использовать&&
оператор:
let user = {}; // user 没有 address 属性
alert( user.address && user.address.street && user.address.street.name ); // undefined(不报错)
В свою очередь, атрибуты на всем пути оцениваются с помощью операции И, чтобы убедиться, что все узлы существуют (если нет, вычисление останавливается), но это все равно не элегантно.
Как видите, мы по-прежнему несколько раз повторяем имена свойств объекта в коде. Например, в приведенном выше кодеuser.address
Это повторялось трижды.
Вот почему необязательная цепочка?.
был добавлен в язык программирования JavaScript. То есть полностью решить все вышеперечисленные проблемы!
дополнительная цепочка
если необязательная цепочка?.
Предыдущая частьundefined
илиnull
, он останавливает вычисления и возвращается к этому разделу.
Для краткости в оставшейся части этой статьи мы будем говорить, что если свойство не является ниnull
ни одинundefined
, то он "существует".
Другими словами, напримерvalue?.prop
:
- если
value
существует, результат тот же, что иvalue.prop
такой же, - иначе (когда
value
дляundefined/null
время) затем вернутьсяundefined
.
Ниже приведено использование?.
безопасный доступuser.address.street
Путь:
let user = {}; // user 没有 address 属性
alert( user?.address?.street ); // undefined(不报错)
Код лаконичен и понятен, нет необходимости несколько раз повторять название свойства.
даже объектuser
не существует, используйтеuser?.address
Не проблема прочитать адрес:
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
осторожность:?.
Синтаксис делает значение, предшествующее ему, необязательным, но не действует на значение, следующее за ним.
Например, вuser?.address.street.name
середина,?.
разрешатьuser
дляnull/undefined
, но не более того. Доступ к более глубоким свойствам осуществляется обычным способом. Если мы хотим, чтобы некоторые из них также были необязательными, нам нужно использовать больше?.
заменить.
.
Не злоупотребляйте необязательными цепочками:
мы должны только
?.
Используется там, где что-то не может существовать.Например, если согласно логике нашего кода,
user
объект должен существовать, ноaddress
является необязательным, то мы должны написатьuser.address?.street
, вместо этогоuser?.address?.street
.Так что если
user
Так уж получилось, что поскольку ошибка становится неопределенной, мы видим ошибку программирования и исправляем ее. В противном случае ошибки в коде устраняются в неподходящих местах, что затрудняет отладку.
дополнительная цепочка
?.
Предыдущая переменная должна быть объявленаЕсли переменная не объявлена
user
,Такuser?.anything
вызовет ошибку:// ReferenceError: user is not defined user?.address;
?.
Предыдущая переменная должна быть объявлена (например,let/const/var user
или как параметр функции). Необязательная цепочка работает только для объявленных переменных.
эффект короткого замыкания
Как было сказано ранее, если?.
Если левая часть не существует, работа немедленно останавливается («эффект короткого замыкания»).
Таким образом, если последуют какие-либо вызовы функций или побочные эффекты, ни один из них не будет выполнен.
Например:
let user = null;
let x = 0;
user?.sayHi(x++); // 没有 "sayHi",因此代码执行没有触达 x++
alert(x); // 0,值没有增加
Другие варианты: ?.(), ?.[]
дополнительная цепочка?.
Не оператор, а специальная синтаксическая конструкция. Он также работает с функциями и квадратными скобками.
Например, будет?.()
Используется для вызова функции, которая может не существовать.
В приведенном ниже коде у некоторых пользователейadmin
метод, а некоторые нет:
let userAdmin = {
admin() {
alert("I am admin");
}
};
let userGuest = {};
userAdmin.admin?.(); // I am admin
userGuest.admin?.(); // 啥都没有(没有这样的方法)
В этих двух строках кода мы сначала используем запись через точку (user1.admin
) получитьadmin
свойство, так как пользовательский объект должен существовать, читать его безопасно.
потом?.()
проверит часть слева от него: еслиadmin
функция существует, затем вызовите ее для запуска (дляuser1
). иначе (дляuser2
) работа останавливается без ошибок.
Если мы хотим использовать квадратные скобки[]
вместо записи через точку.
для доступа к свойствам, синтаксису?.[]
также можно использовать. Как и в предыдущем примере, он позволяет безопасно читать свойства возможно несуществующего объекта.
let user1 = {
firstName: "John"
};
let user2 = null; // 假设,我们不能授权此用户
let key = "firstName";
alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined
alert( user1?.[key]?.something?.not?.existing); // undefined
Кроме того, мы также можем?.
а такжеdelete
использовать вместе:
delete user?.name; // 如果 user 存在,则删除 user.name
мы можем использовать
?.
безопасно читать или удалять, но не писать:дополнительная цепочка
?.
Не может использоваться в левой части оператора присваивания.Например:
let user = null; user?.name = "John"; // Error,不起作用 // 因为它在计算的是 undefined = "John"
Это еще не так умно.
Суммировать
дополнительная цепочка?.
Есть три формы грамматики:
-
obj?.prop
-- еслиobj
вернуть, если существуетobj.prop
, иначе возвратundefined
. -
obj?.[prop]
-- еслиobj
вернуть, если существуетobj[prop]
, иначе возвратundefined
. -
obj.method?.()
-- еслиobj.method
звоните если естьobj.method()
, иначе возвратundefined
.
Как мы видели, эти синтаксические формы просты в использовании.?.
Проверьте, является ли левая частьnull/undefined
, если нет, продолжайте операцию.
?.
Цепочки позволяют нам безопасно получать доступ к вложенным свойствам.
Тем не менее, мы должны соблюдать осторожность?.
, его целесообразно использовать только тогда, когда нет проблем с отсутствием левой части. Для того, чтобы в коде были программные ошибки, от нас их не скроют.
Учебники по современному JavaScript: учебные пособия по современному JavaScript с открытым исходным кодом, от начального до продвинутого.Рекомендовано официальной документацией React, учебным пособием по JavaScript вместе с MDN..
Читайте онлайн бесплатно:zh.javascript.info
Найдите общедоступный аккаунт WeChat «Technology Talk», подпишитесь на более интересный контент.