ECMAScript语言规范的第11个版本发布(ES2020)。来看看怎么使用它们。
String.prototype.matchAll
我们知道,原来的 String 原型中,已经提供 match
方法,如:
const str = 'hello1hello2hello3'
const reg = /hello(\d+)/
const match = str.match(reg)
// ["hello1", "1", index: 0, input: "hello1hello2hello3", groups: undefined]
这时我们发现,他只能拿到一组匹配结果,当我们尝试在正则中加入全局 g 时。
const matches = str.match(reg) // ["hello1", "hello2", "hello3"]
只能拿到一个只有完整匹配结果的 string[]
,那种在非全局情况下复杂匹配结果没有了。
而 matchAll
就给我带来期望的结果:
const matchIterator = str.matchAll(reg) // RegExpStringIterator
我们发现,返回的结果是一个迭代器(Iterator
),可以使用 for of 遍历。
for (const match of matchIterator) {
console.log(match);
// 第一次结果: ["hello1", "1", index: 0, input: "hello1hello2hello3", groups: undefined]
}
如果你想要数组的形式,可以通过 ...
运算符或者 Array.from()
转化。
const matches1 = [...str.matchAll(reg)]
const matches2 = Array.from(str.matchAll(reg))
BigInt
我们熟知的 Number
类型只能安全的表示 -(2^53-1) 至 2^53-1 范的值,即 Number.MIN_SAFE_INTEGER
到 Number.MAX_SAFE_INTEGER
之间,超过则不能做到精确计算。
为了解决这个问题,引入了 BigInt
类型:
const bigIntNum1 = 9007199254740991n
const bigIntNum2 = BigInt(9007199254740991)
BigInt
是跟 Number
一样,是原始数据类型:
typeof 1 // number
typeof 1n // bigint
Dynamic import 按需加载
ES2020提案引入 import()
函数,支持动态加载模块:
import('./foo.js')
import() 返回一个 Promise 对象,我们可以在 then 中获取到相应的 export 内容。
// foo.js
export a = 1
export b = 2
// home.js
import(`./foo.js`)
.then(({a, b})=>
// 加载成功的回调
})
.catch(err => {
// 加载失败的回调
})
import() 的加入解决了之前 esm 中只能顶层加入,静态解析的不足。
Promise.allSettled
Promise.allSettled
提供了另外一种并发执行异步任务的处理方式。
跟我们常见的 Promise.all 相比:
-
allSettled
需要等其中的所有任务 resolve 或 reject 后才会改变 status;all
所有任务都 resolve 后改变状态。 -
allSettled
无论其中异步任务是fulfilled
还是rejected
,最终状态都只有fulfilled
;all
一旦有任务的变成rejected
,本身的状态也会变成rejected
。 -
allSettled
让我们更加自由的处理所有并发任务的结果。
const resolved = Promise.resolve(true);
const rejected = Promise.reject('custom error');
Promise.allSettled([resolved, rejected]).then(results => {
console.log(results)
// [
// { status: 'fulfilled', value: true },
// { status: 'rejected', reason: 'custom error' }
// ]
})
如上:allSettled 是不会进到 catch 回调中,在 then 回调的返回每个异步任务的结果。
globalThis
之前,你想写同时支持 Node 和 Browser 环境的代码,获取全局对象会有点费劲:
- Browser 环境中,全局对象是 window,但 Node 和 Web Worker 没有 window。
- Browser 和 Web Worker 里面,self 也指向顶层对象,但是 Node 没有 self。
- Node 里面,全局对象是global,但其他环境都不支持。
- 还有 this,受上下文影响,很容易出错。
要获取全局对象,可以封装一个全局函数:
function getGlobal() {
if (typeof self !== 'undefined') {
return self
}
if (typeof window !== 'undefined') {
return window
}
if (typeof global !== 'undefined') {
return global
}
throw new Error('找不到全局对象')
}
在ES2020标准下,我们可以在任意上下文和环境下通过 globalThis
获取到全局对象。
Nullish coalescing Operator 空值合并运算符
设置默认值最常见的做法就是使用 ||
:
const vip = userInfo.vip || '非vip'
但是在 JS 中空字符串,0等在进行判断时,被当为 false 处理。上面的 vip 0 的结果就会变成 非vip,这个显然是错误的,为了符合我们预期,我们得这么写:
const vip = userInfo.vip == null ? '非vip' : userInfo.vip
而使用空值合并运算符,能获得简洁的写法:
const vip = userInfo.vip ?? '非vip'
Optional chaining 可选链
你是否还记得,为了判断一个多层级对象,写过以下代码:
if (a && a.b && a.b.c && a.b.c.d) {
// do more
}
如果不这么做又容易获得 TypeError
成就。
在最新的可选链中,大可不必,可以这么写:
if (a?.b?.c?.d) {
// do more
}
在 ?
后面的字段,如果有就返回相应的值,没有返回 undefined
:
const obj = { a: 1 }
obj?.a // 1
obj?.b // undefined
obj?.a?.b // undefined
合集
- ES2021(ES12)新特性解读
- ES2020(ES11)带来的新特性
- ES2019(ES10)带来的9个新特性
- ES2018(ES9)新特性
- ES2017(ES8)新特性
- ES2016(ES7)新特性