新增运算符

逸男2022年8月6日
  • JavaScript
大约 4 分钟

新增运算符

质数运算符 ** 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()
}

这样的层层判断非常麻烦,因此 ES2020open in new window 引入了“链判断运算符”(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 的值为0NaNfalse或者''的情况下,会发生意料之外的问题——被认定为没有值,从而使用了默认值。

为了避免这种情况,ES2020open in new window 引入了一个新的 Null 判断运算符??

使用空值合并运算符

let a = 0
let b = a ?? 1 // 0

它的行为类似||,但是只有运算符左侧的值为nullundefined时,才会返回右侧的值。

0??1 // 0
false:1 // false
NaN??1 // NaN
''??1 // ''

undefined??1 // 1
null ?? 1 //1

逻辑赋值运算符 ||= &&= ??= ES2021

ES2021 引入了三个新的逻辑赋值运算符open in new window(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

最新提案(尚未进入标准)

上次编辑于:
贡献者: yinan