可选链
可选链 ?.
是一个特殊的语法结构,一种访问嵌套对象属性的安全的方式。即使中间的属性不存在,也不会出现错误。?.
检查左边部分是否为 null/undefined
,如果不是则继续运算。
let user = {}
console.log(user.address.street);//Error
console.log(user.address.street.name);//Error
//因为 user.address 为 undefined,尝试读取 user.address.street 会失败,并收到一个错误。
对于上述情况,我们有三种方案来处理:
//方案一:
let user = {}
console.log(user.address ? user.address.street : undefined);
console.log(user.address ? user.address.street ? user.address.street.name : null : null)
//方案二:
let user = {}
console.log(user.address && user.address.street);
console.log(user.address && user.address.street && user.address.street.name)
//方案三:
let user = {}
console.log(user?.address?.street);//结果为undefined不报错
console.log(user?.address?.street?.name);//结果为undefined不报错
//如果可选链 ?. 前面的值为 undefined 或者 null,它会停止运算并返回 undefined。
三种方案比较起来,使用可选链,最优雅简洁。
但需要注意:?.
语法使其前面的值成为可选值,但不会对其后面的起作用。
例如,在 user?.address.street.name
中,?.
允许 user
为 null/undefined
(在这种情况下会返回 undefined
)也不会报错,但这仅对于 user
。更深层次的属性是通过常规方式访问的。如果我们希望它们中的一些也是可选的,那么我们需要使用更多的 ?.
来替换 .
。
我们可以用?.()
调用一个可能不存在的函数:
let userAdmin = {
admin() {
console.log("I am admin");
}
};
let userGuest = {};
userAdmin.admin?.(); // I am admin
userGuest.admin?.(); // 啥都没有(没有这样的方法)
//?.() 会检查它左边的部分:
//如果 admin 函数存在,那么就调用运行它(对于 userAdmin)。
//否则(对于 userGuest)运算停止,没有报错。
如果我们想使用方括号 []
而不是点符号 .
来访问属性,可以使用 ?.[]
。它允许从一个可能不存在的对象上安全地读取属性。
let key = "name";
let user1 = {
name: "John"
};
let user2 = null;
alert(user1?.[key]); // John
alert(user2?.[key]); // undefined
空值合并运算符
空值合并运算符是一种获得两者中的第一个“已赋值的非null/undefined
”值的语法。换句话说,如果第一个参数不是 null/undefined
,则 ??
返回第一个参数。否则,返回第二个参数。
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// 显示第一个已赋值的非null/undefined的值:
console.log(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
// 显示第一个真值:
console.log(firstName || lastName || nickName || "Anonymous"); // Supercoder
// || 无法区分 false、0、"" 和 null/undefined。
-
??
运算符的优先级非常低,仅略高于?
和=
,因此在表达式中使用它时请考虑添加括号。 -
如果没有明确添加括号,不能将其与
||
或&&
一起使用。let height = 0; // || 无法区分 false、0、"" 和 null/undefined。 console.log(height || 100); // 100 console.log(height ?? 100); // 0
let height = null; let width = null; // 重要:使用括号 let area = (height ?? 100) * (width ?? 50); console.log(area); // 5000 //否则,如果我们省略了括号,则由于 * 的优先级比 ?? 高,它会先执行,进而导致错误的结果。