「前端每日一问(44)」用过空值合并运算符 (??)吗?

276 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

本题难度:⭐

答:

空值合并操作符?? )是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

为变量赋默认值

如果想为一个变量赋默认值,通常的做法是使用逻辑或操作符(||

let foo = undefined

let res = foo || 'default value'

console.log(res) // 输出 'default value'

然而,由于 || 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0, '', NaN, null, undefined)都不会被返回。

假设我们的程序中 0''NaN 是有意义的,我们需要用到它,就会出错,看下面的例子:

let length = 0
let res = length || 10

console.log(res) // 输出结果为 10,本来期望输出 0

这个时候,就可以使用空值合并运算符 (??)来解决类似问题。

let length = 0

console.log(length ?? 10) // 输出 0
console.log(undefined ?? 10) // 输出 10 
console.log(null ?? 10) // 输出 10 
console.log(NaN ?? 10) // 输出 NaN
console.log('' ?? 'default value') // 输出 ''

使用空值合并操作符,左侧的操作数只要不为 null 或者 undefined,都认为是有效值,都返回左侧的操作数。

左侧的操作数如果是 null 或者 undefined,就返回右侧的默认值。

逻辑空赋值(??=)

逻辑空赋值运算符 (x ??= y) 仅在 x 是 null 或 undefined 时对其赋值。

let x = 0
let y = 100
x ??= y
console.log(x) // 0
let x = undefined
let y = 100
x ??= y
console.log(x) // 100
let userInfo = {}

userInfo.name ??= 'xxx'

console.log(userInfo.name) // 'xxx'
let userInfo = {
  name: 'lin'
}

userInfo.name ??= 'xxx'

console.log(userInfo.name) // 'lin'

条件判断代码是否执行

执行下面的逻辑,看一下什么情况下,右侧的逻辑才会执行

true && console.log('&& 左侧为 true,执行右侧逻辑')
false && console.log('&& 左侧为 false,执行右侧逻辑')
null && console.log('&& 左侧为 null,执行右侧逻辑')
undefined && console.log('&& 左侧为 undefined,执行右侧逻辑')

console.log('-------------- ')

true || console.log('|| 左侧为 true,执行右侧逻辑')
false || console.log('|| 左侧为 false,执行右侧逻辑')
null || console.log('|| 左侧为 null,执行右侧逻辑')
undefined || console.log('|| 左侧为 undefined,执行右侧逻辑')

console.log('-------------- ')

true ?? console.log('?? 左侧为 true,执行右侧逻辑')
false ?? console.log('?? 左侧为 false,执行右侧逻辑')
null ?? console.log('?? 左侧为 null,执行右侧逻辑')
undefined ?? console.log('?? 左侧为 undefined,执行右侧逻辑')

image.png

测试结论是:?? 运算符不适合这个场景,要简写执行代码的逻辑,左侧为 true 用 &&,左侧为 false 用 || 就行。

与可选链操作符 ?. 的关系

这俩操作符除了长得像,没有任何关联,他们被设计出来,分别解决了不同场景的问题。

关于可选链操作符,可以参考文末的链接。

兼容性

image.png 空值合并运算符 (??)和 逻辑空赋值(??=)的兼容性都是一样的,chrome >= 80,不是很好。

不过 babel 对这个特性做了兼容的,一般项目都会引 babel,所以就放心地在项目中使用吧。

image.png

结尾

阿林水平有限,文中如果有错误或表达不当的地方,非常欢迎在评论区指出,感谢~

如果我的文章对你有帮助,你的👍就是对我的最大支持^_^

你也可以关注《前端每日一问》这个专栏,防止失联哦~

我是阿林,输出洞见技术,再会!

上一篇:

「前端每日一问(43)」用过可选链操作符( ?.) 吗?

下一篇:

「前端每日一问(45)」什么是变量提升和暂时性死区