在实习过程中发现项目代码中取值操作中大量使用的是 ?. 以及 ?? 操作符,是我之前没有怎么使用过的,不太了解,所以写篇文章来加深自己的印象。
本文主要参考MDN文档:developer.mozilla.org/zh-CN/docs/…
以及一些其它人的文章
可选链操作符(?.)
概述
可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。
其功能类似于 . 链式操作符,不同之处在于,在引用为空 null 或者 undefined 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。
const obj = {
name: 'zyh',
friends: {
name: 'erfei'
}
}
// 可选链操作符
const friendName = obj.friends?.name
console.log(friendName); // erfei
// 普通取值
const testName = obj.friends.name
console.log(testName); // erfei
语法
obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)
描述
通过连接的对象的引用或函数是 undefined 或 null 时,可选链操作符提供了一种方法来简化被连接对象的值访问
比如存在一个嵌套结构的对象,不使用可选链的话查找一个深度嵌套的子属性时,需要验证之间的引用
let test = obj.first && obj.first.second
这是因为为了避免报错在访问 obj.first.second 之前,要保证 obj.first 的值不是 null 也不是 undefined,而不对 obj.first 进行校验则有可能抛出错误
而在使用可选链操作符(?.)后,访问 obj..first.second 不再需要明确的校验 obj.first 的状态
let test = obj.first?.second
通过使用 ?. 操作符取代 . 操作符,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);
作用
1.函数调用
当尝试使用一个不可能存在方法时也可以使用可选链,使表达式自动返回undefined而不是抛出一个异常
2.处理可选的回调函数或者事件处理器
如果使用解构赋值来结构一个对象的回调函数或fetch方法,可能得到不能当作函数直接调用的不存在的值,除非已经校验了存在性。而使用 ?. 可以忽略二外的校验
function dosomething(onContent, onError) {
try {
// do something
} catch(err) {
if(onError) {
onError(err.message)
}
}
}
// 使用可选链
function dosomething(onContent, onError) {
try {
// do something
} catch(err) {
onError?.(err.message)
}
}
3.表达式
当使用方括号与属性名的形式来访问属性时,也可以使用可选链操作符
let test = obj?.['prop' + 'Name']
4.访问数组元素
let arr = arr?.[5]
注意: 可选链不能用于赋值
兼容性
不支持 IE ,其余都支持
空值合并运算符(??)
概述
空值合并运算符是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数
语法
leftExpr ?? rightExpr
作用
1.可为常量提供默认值
使用空值合并操作符保证常量不为 null 或者 undefined
const nullValue = null;
const emptyText = ""; // 空字符串,是一个假值,Boolean("") === false
const someNumber = 42;
const valA = nullValue ?? "valA 的默认值";
const valB = emptyText ?? "valB 的默认值";
const valC = someNumber ?? 0;
console.log(valA); // "valA 的默认值"
console.log(valB); // ""(空字符串虽然是假值,但不是 null 或者 undefined)
console.log(valC); // 42
2.为变量赋默认值
以前为变量赋默认值通常做法使使用逻辑或操作符(||),但逻辑或操作符左侧的操作数会被强制转换成布尔值用于求职,任何价值都不会被返回。这就会导致如果使用 0,' ',NaN 作为有效值时就会出现不可预料的后果
但空值操作符可以避免这种陷阱,其只有在第一个操作数为 null 或 undefined 时返回第二个操作数
3.短路
与 OR 和 AND 逻辑操作符类似,当左表达式不为 null 或 undefined 时,不会对右表达式进行求值
注意:空值合并操作符不能与 AND 或 OR 操作符共用
兼容性
不支持 IE 和 Opera Android,其余都支持
总结
空值合并操作符与可选链操作符存在关系,空值合并操作符针对 undefined 和 null 两个值,可选链操作符也是如此。因此可以在访问属性可能为 undefined 与 null 的对象时,空值合并操作符可以在使用可选链时设置一个默认值