可选链操作符与空值合并操作符
目的
因为在项目 Code Review 时发现部分新人对可选链操作符 ?.
的理解有误,特此记录一下其含义及用法;顺带提一下与其同时出现的空值合并操作符 ??
可选链操作符
MDN引用:
可选链操作符(?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?.
操作符的功能类似于.
链式操作符,不同之处在于,在引用为空(nullish ) (null
或者undefined
) 的情况下不会引起错误,该表达式短路返回值是undefined
。与函数调用一起使用时,如果给定的函数不存在,则返回undefined
。
如果上面的解释你不太明白,可以先看下面的例子:
在一个项目中,使用一些对象属性或调用对象方法时,为了安全,我们一般都会需要先判断这个对象是否存在,以及属性是否存在等;尤其当数据是由后端接口返回的情况下,更要加上一些空值判断。
比如:
1 | if (res && res.data && res.data.success) { |
类似这种判断贯穿整个项目很多地方,写的时候很是繁琐;可选链操作符就是为了解决这个问题的,上面的判断改用可选链操作符的话,可以这么写:
1 | if (res?.data?.success) { |
是不是简单清晰明了?
可选链的作用是判断它的前一个数据是否是 undefined
或者 null
;如果是,则不再执行后续操作,直接返回 undefined
;如果不是,就可以继续访问后续属性,以返回该属性的结果。
还是说上面的例子,它的实际运行情况是这样的:
1 | if ( |
短路
可选链操作符是一种短路运算;当左侧操作数为 null
或 undefined
时,右侧如果有表达式,是不会被执行的。
看了上面的解析例子,你能大概理解吗?
测试:
1 | let arr = null; |
语法
看了例子,大家应该也知道在对象属性的访问时,要如何使用可选链操作符了,但是其他如数组、函数调用该如何使用可能还不太清楚,这里也写一下
1 | // 对象属性 |
虽然最后这个混合的例子有点儿那啥,但是也是为了让你们能更清楚的了解一下如何使用,就不要吐槽了。
不能被赋值
可选链不能用于赋值操作符的左侧,即不能给一个可选链赋值。
1 | let obj = null; |
空值合并操作符
MDN引用:
空值合并操作符(??
)是一个逻辑操作符,当左侧的操作数为null
或者undefined
时,返回其右侧操作数,否则返回左侧操作数。
提到空值合并操作符,就必须提一下逻辑或操作符 (||
),它们两个乍一看很相似,实际却是不同的。
空值合并操作符仅针对左侧操作数为 null
或 undefined
时,才返回右侧操作数;而逻辑或操作符则是针对左侧操作数为 falsy 时,就返回右侧操作数。
而在 JavaScript 中的 falsy 数据,不止 null
和 undefined
两种,其他还有 false
, 0
, NaN
, ''
这些数据。
具体可以看下面的示例:
1 | null ?? 'default'; // 'default' |
了解了吗?当左侧操作数为 null
和 undefined
时,空值合并操作符和逻辑或操作符的结果是一致的,但当左侧操作数为其他 falsy 值时,二者就不同了。
短路
类似逻辑操作符,空值合并操作符也是一个短路运算:
1 | function f1() { |
其他
空值合并运算符(??
)还有一点需要注意的是,它不能和 逻辑与运算符(&&
) 和 逻辑或运算符(||
) 混合使用。
1 | null || undefined ?? 1; // 抛出 SyntaxError |
不过如果使用圆括号将它们进行分组隔开的话,则没问题:
1 | (null || undefined) ?? 1; // 1 |
参考资料
- MDN-可选链操作符
- MDN-空值合并运算符