一、`?.` 链判断运算符
有时候我们想要获取对象中的一个值,例如
1
const firstName = user.profile.name.firstName
profile可能为undefined
,name可能为null
的时候,我们需要做如下判断
1
2
3
4
const firstName=user&&
user.profile&&
user.profile.name&&
user.profile.name.firstName
我们可以使用lodash库来简化这些:
1
2
import { get } from 'lodash'
const firstName = get(user, ['profile', 'name', 'firstName'])
1、es6中为本机提供了解决方案
1
const firstName = user?.profile?.name?.firstName
?.
运算符视为一个短路,if the expression up until this point is null or undefined, then the whole expression evaluates to undefined
。如果?.
后面为null
或undefined
,阻断后续执行,整个表达式的结果为undefined
。
1
2
3
4
5
6
const read =>user=>user.profile?.name?.firstName
read() // <- Error 因为user为undefined
read({}) // <- undefined
read({profile: {}}) // <- undefined
read({ profile: { name: { firstName: 'Bob' } } }) // <- 'Bob'
2、`?.`可以出现在任何表达式之后,函数和数组
1
2
3
4
5
let a = null
// 函数调用
a?.() // <- undefined 不会报错
// 数组
a?.[0] // <- undefined 不会报错
1
2
3
4
5
6
7
delete a?.b
// 等同于
a == null ? undefined : delete a.b
(a?.b).c
// 等同于
(a == null ? undefined : a.b).c
GitHub上找到的提案文档
3、以下情况会报错
1
2
3
4
5
6
7
8
9
10
11
// 构造函数
new a?.()
new a?.b()
// 链判断运算符的右侧有模板字符串
a?.`{b}`
a?.b`{c}`
// 链判断运算符的左侧是 super
super?.()
super?.foo
// 链运算符用于赋值运算符左侧
a?.b = c
二、`??`是ES2020 引入了一个新的 Null 判断运算符
为value赋值的时候,如果curValue为null的时候,就默认为defautValue
1
value= curValue || defautValue
这样写会有问题,如果curValue=false或者0时,会出现错误的赋值。大家可以这样写:
1
value= curValue ?? defautValue
只有运算符左侧的值为null或undefined时,才会返回右侧的值。
1、优先级
??
有一个运算优先级问题,它与&&和||的优先级孰高孰低。现在的规则是,如果多个逻辑运算符一起使用,必须用括号表明优先级,否则会报错
1
2
3
4
5
// 报错
lhs && middle ?? rhs
lhs ?? middle && rhs
lhs || middle ?? rhs
lhs ?? middle || rhs
1
2
3
4
5
6
7
8
9
// 正确
(lhs && middle) ?? rhs;
lhs && (middle ?? rhs);
(lhs ?? middle) && rhs;
lhs ?? (middle && rhs);
(lhs || middle) ?? rhs;
lhs || (middle ?? rhs);
(lhs ?? middle) || rhs;
lhs ?? (middle || rhs);