TL; TR
Выражение проверяется на наличие non-undefined
, not-null
значений с помощью ?
и в любой момент, если обнаруживается одно из этих значений, цепочка просто разрывается и возвращает undefined
.
Очень важно отметить, что она защищает только от значений undefined
и null
, а не от ложности значения, т.е. он все равно будет передавать другие ложные значения, такие как NaN или "".
Длинное объяснение
Начнем с цитирования MDN
Необязательный оператор цепочки предоставляет способ упростить доступ к значениям через подключенные объекты, когда возможно, что ссылка или функция могут быть неопределенными или нулевыми.
Рассмотрим такой объект:
var obj = {
a: {
b: 1
},
}
Теперь для проверки obj
, obj
peroperty a
, а затем свойства a
b
как undefined
и null
, вам может потребоваться сделайте что-нибудь вроде этого:
obj && obj.a && obj.a.b
Дополнительное связывание предоставляет вам альтернативу этому. Вы можете просто сделать это так:
obj?.a?.b
Теперь предположим, что a
оказывается функцией, которая возвращает объект со свойством b
, которое содержит значение 1
. Примерно так:
var obj = {
a: function{
return {b:1}
},
}
Итак, как вы теперь проверяете obj
и его поля для глубоко вложенных b
? Что ж, вы можете сделать что-то вроде этого:
obj && obj.a && typeof obj.a === 'function' && obj.a() && obj.a().b
Или вы можете просто сделать
obj?.a()?.b
Это просто означает проверку obj
на наличие неопределенных и ненулевых значений (если это), затем проверьте obj?.a()
на то же самое, (если это так) выполните метод a()
obj. Если после выполнения метод возвращает значение (которое не является undefined
или null
), тогда получите из него значение свойства b
.
В любой момент во время этой проверки , если будет найдено значение undefined
или null
, просто разорвите цепочку и верните undefined
Однако это не удастся, если a
не является функцией, которая было проверено с помощью typeof obj.a === 'function'
в предыдущем выражении. Также обратите внимание, что на этом этапе, если obj.a()
вернет, скажем, «baz», он будет выполнен как "baz".b
, что даст вам undefined
.
С этими знаниями мы можем расшифровать это выражение легко:
obj.a?.().b
Оно проверяет, соответствует ли obj.a
non-undefined
, not-null
. Если это так, выполните obj.a () (обратите внимание, что он выдаст ошибку, если obj.a
не является функцией, но возвращает, скажем, число 5
)
Если obj.a()
происходит, выполните успешно, тогда .b
перенастроенного значения будет проверено.
Теперь это осталось
obj.a?.()?.b
Ну, это также выполняется так же, как и наши предыдущие исполнения:
проверка obj.a
, если это not-null
и non-undefined
. Если это так, выполните obj.a
. Если это также non-null
и non-undefined
, выполните obj.a()
и т. Д.
Если в любой момент во время проверки будет обнаружено значение null
или undefined
, цепочка просто разорвется .
Очень важно отметить, что наш оператор ?
защищает только от undefined и null, а не от других ложных значений.
Учитывайте это
var a = undefined
var myVal = a?.details.b;
alert(a) //will return undefined
var a = ""
var myVal = a?.details.b;
alert(a) //Our guard fails us here and simply throws an error