前言:如果想安全访问对象的嵌套属性或调用函数以及处理可能为 nullundefined 的值,我们可以使用 逻辑与&& 和 逻辑或|| 来处理。虽然有效,但这些方法的主要用途是进行逻辑判断,而不是空值处理。所以在ES2020引入了可选链(?.空值合并(??,它们很好地解决了以前方法引起的一些问题。


一、假值和空值

首先我们需要了解假值和空值的概念:

  • 假值:在 JavaScript 中,以下值会被当作 false 处理:

    falsenullundefined0-0NaN""(空字符串)

  • 空值:仅指 nullundefined

二、安全访问

当我们想要访问对象的嵌套属性或调用函数时,可能会遇到某个对象属性或调用者为null undefined的情况,而我们又不想让其报错导致终止程序,这时就可以使用以下两种方法来检查访问或调用的过程,它们允许在遇到这种情况时避免抛出错误。

1. 使用逻辑与运算符 (&&)

假设我们有一个用户对象 user,其中包含地址信息 address,而地址信息中又包含城市信息 city

// 创建一个user对象
const user = {
    address: {
        city: "Beijing"
    }
};

如果此时我们直接访问user.address.city,那么这是安全的。但如果 user.address 不存在,则会抛出错误。在早期,我们通常使用逻辑与运算符来避免这种情况:

console.log(user.address && user.address.city); // 输出 "Beijing"
console.log(user.unknown && user.unknown.city); // 输出 undefined

但是对于更深层次的嵌套属性,需要进行多层检查以确保每一层都不是 nullundefined,使用&&就会有些繁琐:

// 假定有个obj对象其中嵌套了3个对象
const value = obj && obj.level1 && obj.level1.level2 && obj.level1.level2.level3;

如上,这种方法虽然可用,但代码会变得冗长、难以阅读,并且容易出错。同时每次添加或修改属性层级时都需要调整代码。

2. 使用可选链操作符(?.

?. 是专门用于 “安全访问” 的,它极大地简化了这种检查过程,避免了报错:

// 创建一个user对象
const user = {
    address: {
        city: "Beijing"
    }
};

console.log(user?.address?.city); // "Beijing"
console.log(user?.unknown?.city); // "undefined"
console.log(user?.address?.phone); // "undefined"

显而易见,?. 的工作过程就像正常访问一样,不过只要中间的某个节点为空值,那么表达式就会返回undefined,而不是抛出错误。

同时即便访问不存在的属性,也不会报错,仍然返回undefined,极大地提高了代码的健壮性。

小总结:
  • && 是通过逻辑判断实现的,所以只要运算符的左侧为假值,都会短路并返回该假值,否则返回右侧值;
  • ?. 是专门实现安全访问的,所以只要访问的过程中出现空值,都会短路并返回undefined,否则返回右侧值;
三、空值处理(提供默认值)

当一个变量可能是 nullundefined 时,我们可以使用以下两种方法为其提供默认值。

1. 使用逻辑或运算符 (||)

在以往,我们使用 || 会有些意外的结果:

假设我们提供数据 data.name ,我们希望在它为空值时使用一个默认名字。

const data = {
    name:null
}

console.log(data.name || "Lihua") // "Lihua"

但是要注意,这种方式不仅会在 nullundefined 时返回默认值,也会在 false, 0, '' (空字符串) 等其他假值情况下返回默认值 ,这可能不是你想要的行为。

2. 使用空值合并操作符(??)

空值合并操作符仅在左侧的操作数为 nullundefined 时返回右侧的默认值,否则返回左侧的操作数。这使得我们可以优雅地处理缺失数据的情况。

console.log(null ?? "default"); // 输出 "default"
console.log(undefined ?? "default"); // 输出 "default"
console.log("Hello" ?? "default"); // 输出 "Hello"
console.log("" ?? "default"); // 输出 ""
小总结:
  • || 是通过逻辑判断实现的,所以只要运算符的左侧为假值,就会返回右侧默认值;
  • ?? 是专门实现空值处理的,所以只要操作符的左侧为空值,就会返回右侧默认值;
四、大总结
  • ?.:安全访问,只认 null/undefined
  • ??:空值默认,只认 null/undefined
  • &&:逻辑与,认所有假值,适合条件判断
  • ||:逻辑或,认所有假值,适合 “任一为真” 的判断
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐