||
运算方法:
只要“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值。
只要“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值。
总结:真前假后
&&
运算方法:
只要“&&”前面是false,无论“&&”后面是true还是false,结果都将返“&&”前面的值;
只要“&&”前面是true,无论“&&”后面是true还是false,结果都将返“&&”后面的值;
零合并操作符 ??
- 零合并操作符 ?? 是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回右侧操作数,否则返回左侧操作数。
- 空值合并操作符一般用来为常量提供默认值,保证常量不为 null 或者 undefined,以前一般使用 || 来做这件事 variable = variable || ‘bar’。然而,由于 || 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0, ‘’, NaN, null, undefined)都不会被返回。这导致如果你使用 0、’’、NaN 作为有效值,就会出现不可预料的后果。
正因为 || 存在这样的问题,而 ?? 的出现就是解决了这些问题,?? 只会在左侧为 undefined、null 时才返回后者,?? 可以理解为是 || 的完善解决方案。
undefined || 'default' // 'default'
null || 'default' // 'default'
false || 'default' // 'default'
0 || 'default' // 'default'
undefined ?? 'default' // 'default'
null ?? 'default' // 'default'
false ?? 'default' // 'false'
0 ?? 'default' // 0
- 另外在赋值的时候,可以运用赋值运算符的简写 ??=
let a = {b: null, c: 10}
a.b ??= 20
a.c ??= 20
console.log(a) // 输出 { b: 20, c: 10 }
可选链操作符 ?.
- 可选链操作符 ?. 允许读取位于连接对象链深处的属性的值,而不必验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为 null 或者 undefined 的情况下不会引起错误,该表达式短路返回值是 undefined。
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。
const obj = {
a: 'foo',
b: {
c: 'bar'
}
}
console.log(obj.b?.c) // 输出 bar
console.log(obj.d?.c) // 输出 undefined
console.log(obj.func?.()) // 不报错,输出 undefined
- 以前可能会通过 obj && obj.a && obj.a.b 来获取一个深度嵌套的子属性,现在可以直接 obj?.a?.b 即可。
可选链除了可以用在获取对象的属性,还可以用在数组的索引 arr?.[index],也可以用在函数的判断 func?.(args),当尝试调用一个可能不存在的方法时也可以使用可选链。
调用一个对象上可能不存在的方法时(版本原因或者当前用户的设备不支持该功能的场景下),使用可选链可以使得表达式在函数不存在时返回 undefined 而不是直接抛异常。
逻辑运算符和赋值表达式
逻辑运算符和赋值表达式,新特性结合了逻辑运算符(&&,||,??)和赋值表达式而JavaScript已存在的 复合赋值运算符有:
操作运算符:+= -= *= /= %= **=
位操作运算符:&= ^= |=
按位运算符:<<= >>= >>>=
现有的的运算符,其工作方式都可以如此来理解
表达式:a op= b
等同于:a = a op b
逻辑运算符和其他的复合赋值运算符工作方式不同
表达式:a op= b
等同于:a = a op (a = b)
a ||= b
//等价于
a = a || (a = b)
a &&= b
//等价于
a = a && (a = b)
a ??= b
//等价于
a = a ?? (a = b)
为什么不再是跟以前的运算公式a = a op b一样呢,而是采用a = a op (a = b)。因为后者当且仅当a的值为false的时候才计算赋值,只有在必要的时候才执行分配,而前者的表达式总是执行赋值操作
??=可用来补充/初始化缺失的属性
const pages = [
{
title:'主会场',
path:'/'
},
{
path:'/other'
},
...
]
for (const page of pages){
page.title ??= '默认标题'
}
console.table(pages)
//(index) title path
//0 "主会场" "/"
//1 "默认标题" "/other"
小结:
&&=:当LHS值存在时,将RHS变量赋值给LHS
||=:当LHS值不存在时,将RHS变量赋值给LHS
??= :当LHS值为null或者undefined时,将RHS变量赋值给LHS