在 JavaScript 引入可选链(optional chaining)和空值合并运算符(nullish coalescing operator)之前,开发者需要使用多种方法来安全地访问对象的嵌套属性以及处理可能为 null 或 undefined 的值。这些方法虽然有效,但存在一些痛点。ES2020 引入的可选链和空值合并运算符则极大地简化了这些问题的处理。
1. 使用逻辑与运算符 (&&)
在早期,判断对象是否包含某个属性并且该属性不是 null 或 undefined,通常使用逻辑与运算符:
var value = obj && obj.prop;
但这种方法仅适用于一层属性检查,对于深层次的嵌套属性,代码会变得冗长且难以维护。
2. 使用逻辑或运算符 (||)
为了提供一个默认值,当变量可能是 null 或 undefined 时,可以使用逻辑或运算符:
var value = obj && obj.prop || defaultValue;
这种方式不仅会在 null 和 undefined 时返回 defaultValue,还会在 false, 0, '' (空字符串) 等其他假值情况下返回 defaultValue,这可能导致不期望的行为。
3. 嵌套检查
对于更深层次的嵌套属性,需要进行多层检查以确保每一层都不是 null 或 undefined:
var value = obj && obj.level1 && obj.level1.level2 && obj.level1.level2.level3;
尽管可以这样使用,但代码会变得冗长、难以阅读,并且容易出错。每次添加或修改属性层级时都需要调整代码。
当对象嵌套层级较深或者属性可能不存在时,我们需要进行一系列的条件判断来避免程序报错。为了简化这些复杂的逻辑,JavaScript 引入了两个非常实用的操作符:可选链操作符(?.) 和 空值合并操作符(??)。今天介绍下这两个操作符的使用方法以及它们背后的原理。
4. 什么是可选链操作符(?.)
(1) 基本概念
可选链操作符(?.)用于简化访问嵌套对象的属性或调用函数时的检查过程。它允许我们在访问可能为 null 或 undefined 的对象属性时避免抛出错误。
(2) 使用场景
假设我们有一个用户对象 user,其中包含地址信息 address,而地址信息中又包含城市信息 city:
const user = {
address: {
city: "Beijing"
}
};
如果我们直接访问 user.address.city,这是安全的。但如果 user.address 不存在,则会抛出错误。这时我们可以使用可选链操作符来避免这种情况:
console.log(user.address?.city); // 输出 "Beijing"
console.log(user.unknown?.city); // 输出 undefined
(3) 工作原理
当使用可选链操作符时,如果左侧的操作数为 null 或 undefined,则整个表达式的值立即变为 undefined,而不会继续尝试访问右侧的属性或调用方法。
console.log(null?.prop); // 输出 undefined
console.log(undefined?.prop); // 输出 undefined
5. 空值合并操作符(??)
(1) 基本概念
空值合并操作符(??)用于提供一个默认值给一个可能为 null 或 undefined 的变量。它只会在操作数为 null 或 undefined 时返回右侧的值,否则返回左侧的操作数。
在以往,
var value = obj && obj.prop || defaultValue;
但是要注意,这种方式不仅会在 null 和 undefined 时返回 defaultValue,也会在 false, 0, '' (空字符串) 等其他假值情况下返回 defaultValue,这可能不是你想要的行为。
(2) 使用场景
当我们希望为某个变量设置一个默认值时,可以使用空值合并操作符。例如,假设我们有一个可能为空的字符串变量 name,我们希望在它为空时使用一个默认名字:
let name = null;
const defaultName = "Guest";
console.log(name ?? defaultName); // 输出 "Guest"
(3) 工作原理
空值合并操作符仅在左侧的操作数为 null 或 undefined 时返回右侧的操作数,否则返回左侧的操作数。这使得我们可以优雅地处理缺失数据的情况。
console.log(null ?? "default"); // 输出 "default"
console.log(undefined ?? "default"); // 输出 "default"
console.log("Hello" ?? "default"); // 输出 "Hello"
6. 结合使用
在实际开发中,我们经常需要结合使用这两种操作符来处理复杂的数据结构。例如,我们可能需要从一个深度嵌套的对象中获取一个值,并为其提供一个默认值:
const user = {
address: {
city: null
}
};
const cityName = user.address?.city ?? "Unknown City";
console.log(cityName); // 输出 "Unknown City"
在这个例子中,首先使用可选链操作符检查 user.address.city 是否存在,如果不存在则返回 undefined。然后,空值合并操作符确保最终结果是 "Unknown City" 而不是 undefined。
通过使用可选链操作符和空值合并操作符,我们可以大大简化对可能为 null 或 undefined 的数据的处理逻辑,使代码更加简洁和易于维护。这两种操作符在处理复杂对象和默认值时提供了强大的支持,是现代JavaScript开发中的重要工具。