以下是mdn的官方解释:
可选链运算符(?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?.
运算符的功能类似于 .
链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined
。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined
。
当尝试访问可能不存在的对象属性时,可选链运算符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链运算符也是很有帮助的。
要搞清楚可选链运算符之前,大家必须知道js在访问一个对象的属性时,如果这个属性时null或者undefined时,是不会报错的,但是如果继续读这个属性的下级时,才会报错,.?就是用来解决这个问题的。
以前做的兜底校验:
let obj = {}
let nestedProp = obj.first || obj.first.second;
// 这是一个简单的校验,保存 first 为 假 值时,不再访问second,以免出现不可预知的错误
let nestedProp = obj.first && obj.first.second;
使用.?(可选链运算符)
let nestedProp = obj.first?.second;
/*
我给大家翻译一下这句话,obj.first是不是 null 或者 undefined 呀?
不是的话我就读first下面的second去啦
是的话我就返回 undefined 啦
*/
/*
mdn的解释:
通过使用 ?. 运算符取代 . 运算符,JavaScript 会在尝试访问 obj.first.second 之前
先隐式地检查并确定 obj.first 既不是 null 也不是 undefined
如果obj.first 是 null 或者 undefined
表达式将会短路计算直接返回 undefined。
*/
// 这个验证等价于下面的这个表达式
let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
// 对函数的验证
let result = someInterface.customMethod?.();
/*
如果有customMethod就执行,没有的话就返回undefined
这里有一点要注意:如果存在一个属性名且不是函数,使用 ?. 仍然会产生一个 TypeError 异常
正在动脑经的同学可能已经发现了,那要是someInterfaceu也是 null 或者 undefined呢?
那么我们就可以写成下面这样
*/
let result = someInterface?.customMethod?.();
/*
如果使用解构赋值来解构的一个对象的回调函数或 fetch 方法
你可能得到不能当做函数直接调用的不存在的值
除非你已经校验了他们的存在性
使用?.的你可以忽略这些额外的校验:
*/
function doSomething(onContent, onError) {
try {
console.log('正确')
}
catch (err) {
if (onError) { // 校验 onError 是否真的存在
onError(err.message);
}
}
}
// 使用可选链进行函数调用
function doSomething(onContent, onError) {
try {
console.log('正确')
}
catch (err) { // 等于少了一个 if (onError) 的判断
onError?.(err.message); // 如果 onError 是 undefined 也不会有异常
}
}
使用.?(可选链运算符)还可以配合 空值合并运算符(??)点击跳转
let customer = {
name: "Carl",
details: { age: 82 }
};
let customerCity = customer?.city ?? "值是unll或者undefined,所以我出现了";
console.log(customerCity); // “值是unll或者undefined,所以我出现了”