12 可选链与空值合并

可选链运算符

可选链运算符 ?. 允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符,不同之处在于,在引用为空 nullish (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

语法:

obj.val?.prop
obj.val?.[expr]
obj.func?.(args)

栗子:

const nestedProp = obj.first?.second

// 等价于
const temp = obj.first
const nestedProp = temp === null || temp === undefined ? undefined : temp.second

实战:

// 可选链和表达式
const nestedProp = obj?.['prop' + 'Name']

// 可选链不能用于赋值
const object = {}
object?.property = 1 // Uncaught SyntaxError: Invalid left-hand side in assignment

// 可选链访问数组元素
const arrayItem = arr?.[42]

空值合并运算符

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

与逻辑或运算符 || 不同,逻辑或运算符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如 ''0)时。

const qty = 0 ?? 42 // 0
const message = '' ?? 'hi!' // ''

const qty = 0 || 42 // 42
const message = '' || 'hi!' // 'hi!'

空值合并运算符可以避免这种陷阱,其只在第一个操作数为 nullundefined 时(而不是其它假值)返回第二个操作数。

短路:与 ORAND 逻辑运算符相似,当左表达式不为 nullundefined 时,不会对右表达式进行求值。

function A() {
  return undefined
}
function B() {
  return false
}
function C() {
  return 'foo'
}

A() ?? C() // A 和 C 都被执行

B() ?? C() // 只执行 B

不能与 ANDOR 运算符共用,因为空值合并运算符和其他逻辑运算符之间的运算优先级/运算顺序是未定义的,这种情况下会抛出 SyntaxError

null || undefined ?? 'foo' // 抛出 SyntaxError
true || undefined ?? 'foo' // 抛出 SyntaxError

// 但是如果使用括号来显式表明运算优先级,是没有问题的
(null || undefined ) ?? 'foo' // 返回 'foo'

需要注意的一点是,空值合并运算符和 JavaScript 中的默认参数是有一点不一样的。因为默认参数只有在 undefined 的情况下才会进行默认值赋值操作,而参数为 null 时不会默认赋值。

可选链运算符和空值合并运算符可以放在一起操作,确保值不存在的时候,有一个兜底的默认值可以给程序使用:

const x = foo?.bar?.() ?? 'default'

最后更新于