可选链运算符 问号点(?.)
?.
运算符与.
运算符类似,可以取对象深处的属性或方法,与.
不同之处在于,当引用为null
或undefined
时,不会引起报错。
校验对象属性
当一个对象下有很多层级,想取其深层级的子属性时,需要进行校验。
const obj = {};
const newAge = obj.name && obj.name.age;
上述代码中如果不对obj.name
进行校验,若obj.name
是null
或undefined
,会报错。
可选链运算符可以简化上述操作。
const obj = {};
const newAge = obj.name?.age;
若obj.name
不存在,则newAge
的值是undefined
,不会报错。
使用可选链运算符会在尝试访问obj.name.age
之前,先隐式地检查并确定obj.name
既不 null
也不是 undefined
。如果obj.name
是 null
或者 undefined
,表达式将会短路计算直接返回 undefined
。
上述代码等价于以下代码,且不会创建临时变量。
let temp = obj.name;
const newAge = temp === null || temp === undefined ? undefined : temp.age;
校验对象方法
尝试调用对象上的一个可能不存在的函数时也可以使用可选链操作符
const obj = {};
const result = obj.fun?.()
如果fun
函数不存在,也不会报错,result
会返回undefined
。
校验回调函数
function doSomething(onContent, onError) {
try {
// ... do something with the data
} catch (err) {
onError?.(err.message); // 如果 onError 是 undefined 也不会有异常
}
}
校验数组索引
let arrayItem = arr?.[3];
短路计算
如果可选链操作符左边是null
或者undefined
,其右边的值将不会被计算。
let a = null;
let x = 0;
let b = a?.[x++];
console.log(x); // x 将不会被递增,依旧输出 0
空值合并运算符 问号问号(??)
??
是一个逻辑运算符,当左边是null
或undefined
时,返回右边的值。
与||
不同的是,||
判断左边为false
时返回右边的值,但0
或''
都是false
,所以二者行为是不同的。
const a = null ?? 'default';
console.log(a);
// 'default'
const b = 0 ?? 1;
console.log(baz);
// 0
与可选链操作符合作
空值合并运算符适合用来赋默认值
const obj = {};
const newAge = obj.name?.age??18;
console.log(newAge)
//18
运算符顺序
空值合并运算符和其他逻辑运算符之间的运算优先级/运算顺序是未定义的,所以与其他运算符合并使用时需要加括号,否则会报错。
null || undefined ?? "foo"; // 抛出 SyntaxError
(null || undefined) ?? "foo"; // 返回 "foo"