新增运算符
新增运算符
**
ES2016
质数运算符 **
用于指数运算
基本使用
3 ** 3 // 27
// 相当于下面的写法
3 * 3 * 3 // 27
注意点
指数运算符是少有的右结合,连用时会从最右边开始计算
2 ** (3 ** 2) // 512
// 运行解析如下
2 ** (3 ** 2)
2 ** (3 * 3)
2 ** 9
2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2
和等号结合使用
指数运算符可以和等号结合使用,形成一个新的赋值运算符 **=
let a = 4
a **= 2
// 等同于 a = a * a
let b = 4
b **= 3
// 等同于 b = b * b * b
?.
ES2020
可选链运算符 有什么用?
在编程过程中如果属性的层级过深,往往需要判断上层对象是否存在,从而避免报错,引起页面加载失败。
let a = {
b: {
c: {
fun() {
console.log('111')
},
},
},
}
a.b.c.fun()
上面的代码中,如果 fun 方法的上层对象有一层不存在,就会导致报错,引起页面加载失败。
之前的解决办法是将上层对象每层都做一下非空判断
if (a && a.b && a.b.c && a.b.c.fun) {
a.b.c.fun()
}
这样的层层判断非常麻烦,因此 ES2020 引入了“链判断运算符”(optional chaining operator)?.
,简化上面的写法。
使用可选链运算符
a?.b?.c?.fun?.()
如果链条中有上层对象为空,就会引起短路机制
,后面的代码不会执行并返回undefined
。
我们可以看到使用可选链操作符后,写法更简单,可读性高。
注意点
在上面的写法中 fun?.()
只能保证 fun 有值,但不能保证 fun 是一个函数。
在数组上使用
arr?.[999]
禁止使用可选链运算符的场景
构造函数
new a?.()
new a?.b()
链判断运算符的右侧有模板字符串
a?.`{b}`
a?.b`{c}`
链判断运算符的左侧是 super
super?.()
super?.foo
链运算符用于赋值运算符左侧
a?.b = c
其他注意点
右侧不得为十进制数值
为了保证兼容以前的代码,允许foo?.3:0
被解析成foo ? .3 : 0
,因此规定如果?.
后面紧跟一个十进制数字,那么?.
不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。
??
ES2020
空值合并运算符 有什么用?
let a = 0
let b = a || 1 // 1
上面的代码中,本意为:判断 a 是否存在,有的话就赋值给 b,没有的话使用默认值 1。
但当 a 的值为0
、NaN
、false
或者''
的情况下,会发生意料之外的问题——被认定为没有值,从而使用了默认值。
为了避免这种情况,ES2020 引入了一个新的 Null 判断运算符??
。
使用空值合并运算符
let a = 0
let b = a ?? 1 // 0
它的行为类似||
,但是只有运算符左侧的值为null
或undefined
时,才会返回右侧的值。
0??1 // 0
false:1 // false
NaN??1 // NaN
''??1 // ''
undefined??1 // 1
null ?? 1 //1
||=
&&=
??=
ES2021
逻辑赋值运算符 ES2021 引入了三个新的逻辑赋值运算符(logical assignment operators),将逻辑运算符与赋值运算符进行结合。
// 或赋值运算符
x ||= y
// 等同于
x || (x = y)
// 与赋值运算符
x &&= y
// 等同于
x && (x = y)
// Null 赋值运算符
x ??= y
// 等同于
x ?? (x = y)
这三个运算符||=
、&&=
、??=
相当于先进行逻辑运算,然后根据运算结果,再视情况进行赋值运算。
它们的一个用途是,为变量或属性设置默认值。
// 老的写法
user.id = user.id || 1
a.b = a.b ?? 22
a.c && (a.c = 33)
// 新的写法
user.id ||= 1
user.id ||= 1
a.b ??= 22
a.c ??= 33