本文简略记录了一下ES2018到ES2021中新增的个性,能够点击新个性具体理解一下。

ES2018/ES9

非转义序列的模板字符串

移除了在带标签的模板字符串中转义序列的语法限度
之前,\u开始一个unicode本义,\x开始一个十六进制本义,\后跟一个数字开始一个八进制本义。这使得创立特定的字符串变得不可能,例如Windows文件门路 C:\uuu\xxx\111

正则表达式Unicode本义

之前, 能够通过字符集的名称来匹配字符, 即s代表空白
/^\s+$/u.test(' ') // true
在es9,增加了Unicode属性本义,模式为\p{...}\P{...},在正则表达式应用标记u

/^\p{White_Space}+$/u.test(' ') // 空格// true/^\p{Script=Greek}+$/u.test('') // 希腊字母// true/^\p{Script=Latin}+$/u.test('Grüße') // 匹配拉丁字母

正则表达式s标记

之前.能够匹配任意字符,除了换行符
es9后,能够通过标记s,这样.就能够匹配换行符
/hello.es9/s.test('hello\nes9') //true

RegExp named capture groups(正则表达式命名捕捉组)

捕捉分组和非捕捉分组

()示意捕捉分组,()会把每个分组里的匹配的值保存起来(存储在内存中),捕捉的子序列稍后能够通过 Back 援用(反向援用) 在表达式中应用
(?)结尾的就是非捕捉分组,不会将匹配的值保存起来,也不能前面援用,其中?:、?=、?<=等都是非捕捉元,应用这些非捕捉元的分组为非捕捉分组
捕捉分组都是通过索引编号的, 这样代码可读性差

const reg = /(\d{4})-(\d{2})-(\d{2})/u;const matched = reg.exec('2018-12-31');matched[0];  // 2018-12-12matched[1];  // 2018matched[2];  // 12matched[3];  // 31

命名捕捉组

es9中,容许命名捕捉组应用符号?<name>, 小括号中匹配内容的名称放在groups里,进步了代码的可读性

const reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/uconst matched = reg.exec('2018-12-31')matched.groups.year;  // 2018matched.groups.month;  // 12matched.groups.day;  // 31

命名捕捉组也能够应用在replace()办法中
例如将日期转换为“年月日”格局:

const reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;'2018-12-31'.replace(reg, '$<year>年$<month>月$<day>日');// 2018年12月31日

正则表达式反向断言(lookbehind)

正向后行断言:?=

模式: (?=pattern)
exp1(?=exp2): 查找前面为exp2的exp1

const reg = /runoob(?=[\d+])/g //匹配数字后面的runoob123456runoob123runoobbdhh // 只会匹配第一个runoob23runoob456runoob789 //两个都好匹配到

负向后行断言: ?!

模式: (?!pattern)
exp1(?!exp2): 查找前面不为exp2的exp1

const reg = /runboo(?![0-9]+)/g // 匹配前面不是数字的runboo1233runboo-google12runoob1233 // 匹配第一个

正向后行断言(es9): ?<=

模式: (?<=pattern)
(?<=exp2)exp1: 查找后面是exp2的exp1

const reg = /(?<=[0-9]+)runboo/g //匹配后面是数字的runboo1234google123runboo456 // 匹配runboo123googlerunboo123runboo456 // 匹配第二个

负向后行断言(es9):?<!

模式: (?<!pattern)
(?<!exp2)exp1: 查找后面不是exp2的exp1

const reg = /(?<=[0-9]+)runboo/g //匹配后面不是数字的runboo1234google123runboo456 // 不能匹配到runboo123googlerunboo123runboo456 // 匹配第一个

扩大运算符(...)

之前...只能用于数组,es9后,也能够用于对象了,用法和数组一样

Promise.finally()

没有参数
之前的Promise的后果要么是胜利then要么是失败catch,使得有些公共逻辑代码必须在两个回调函数外面写(例如:执行状态批改, 删除对话等)
而后就有了finally(),逻辑只放在一个中央,无论Promise运行胜利还是失败,都会运行

new Promise((reslove, reject) => {  // ...}).then((res) => {  // reslove}).catch((err) => {  // reject}).finally(() => {  // complete});

异步迭代

es8中,能够应用async/await在同步的写法中执行异步函数,然而在循环中,循环仍然放弃同步,即在外部异步函数调用之前循环曾经全副实现

async function foo(array) {  for (let i of array) {    await doSomething(i);  }}

es9引入了异步迭代器(asynchronous iterators),使await能够和for...of循环一起应用

async function foo (array) {    for await (let i of array) {        doSomething(i)    }}

ES2019/ES10

可选的catch

try {    //...} cath(unused) {    // ...}//能够省略没有应用到的catch里的变量try {    //...} catch {    //...}

Symbol.prototype.description

只读属性,返回Symbol对象的可形容的字符串

Symbol('desc').description // desc

Object.fromEntries(iterable)

将键值对列表转换为对象
Object.fromEntries() 执行与 Object.entries 互逆的操作:

//将对象转换为数组const arr = Object.entries(obj) // [[key, value]]的模式// 还原回来const obj = Object.fromEntries(arr);

将map对象转为对象:

const map = new Map();map.set('one', 1);map.set('two', 2);const obj = Object.fromEntries(map); // {one: 1, two: 2}

解决URL的查问字符串:

const paramsString = 'param1=foo&param2=baz';const searchParams = new URLSearchParams(paramsString); // { param1: 'foo', param2: 'baz'}

String.prototype.{trimStart, trimEnd}

别离为去掉字符串右边和左边的空格,与trimLeft()和trimRight()雷同
对于Web兼容性,trimLeft() 和trimRight() 将保留为trimStart() 和trimEnd() 的别名。

Array.prototype.{flat, faltMap}

flat([level])办法能够将多维数组展平成一维数组,且有空值时,会抛弃; 可选参数level指定开展几层

// 以前应用concat或reduceconst arr = ['a', 'b', ['c', 'd']];const flattend = [].concat.apply([], arr);// const flattend = [].concat(...arr);

flatMap()办法将map()和flat()组合成一个办法

const arr2 = [[7.1], [8.1], [9.1], [10.1], [11.1]];//想要删除我的项目,只需返回[]// do not include items bigger than 9arr.flatMap(value => {  if (value >= 10) {    return [];  } else {    return Math.round(value);  }}); // [7, 8,9]

ES2020/ES11

String.prototype.matchAll(regexp)

返回一个蕴含所有匹配正则表达式的后果及分组捕捉组的迭代器
regexp参数必须要设置全局模式g,否则会抛出异样
之前咱们通过在循环中调用regexp.exec()来获取所有匹配项信息

const regexp = RegExp('foo[a-z]*','g');const str = 'table football, foosball';let match;while ((match = regexp.exec(str)) !== null) {  console.log(`Found ${match[0]} start=${match.index} end=${regexp.lastIndex}.`);  // expected output: "Found football start=6 end=14."  // expected output: "Found foosball start=16 end=24."}// matchAllconst matches = str.matchAll(regexp);for (const match of matches) {  console.log(`Found ${match[0]} start=${match.index} end=${match.index + match[0].length}.`);}// expected output: "Found football start=6 end=14."// expected output: "Found foosball start=16 end=24."

import()

按需动静导入模块
在之前,依据须要导入模块时只能应用require()
@babel/preset-env中曾经蕴含了@babel/plugin-syntax-dynamic-import,所有只需配置@babel/preset-env
import()返回的是一个Promise对象

// module.jsexport default {  name: 'shenjp'}// index.jsif (true) {  let module = import('./module.js');  console.log(module); // Promise {<pending>  module.then(data => console.log(data)); // Module {default: {name: "shenjp"}, __esModule: true, Symbol(Symbol.toStringTag): "Module"}}

import.meta

为以后运行的模块增加了一个特定host元数据对象

<script type="module" src="my-module.mjs"></script>console.log(import.meta); // { url: "file:///home/user/my-module.mjs" }

BigInt:内置对象

能够示意任意大的整数,本来JavaScript只能示意2^53 -1以内的数字
定义一个BigInt:

// 1、在数字字面量前面加一个nconst big = 10n// 2、调用BigInt()const big2 = BigInt(9007199254740991) // 9007199254740991nconst big3 = BigInt('9007199254740991') // 9007199254740991ntypeof big2 // bigint// 带小数的运算会被取整5n/2n // 2n

留神: 不能用于Math对象中的办法;不能和Number实例混合运算,必须要转换为同一种类型才行(在BigInt转Number时,留神可能会失落精度)
BigInt能够和+、*、-、**(次方)、%和除>>>(因为BigInt都是有符号的)之外的位操作

空值合并运算符(??)

只会右边的值严格等于null或undefined时才应用左边的值

'' || 'default' // default'' ?? 'default' // ''0 || 'defa' // defa0 ?? 'defa' // defa

可选链

当咱们在一个深的树形构造中查找一个属性值会像上面这样:

const name = data && data.info && data.info.name//应用?.const name1 = data?.info?.name//还能够与空值合并运算符搭配应用const name2 = data?.info?.name ?? 'jack'// 其余应用a?.b // a === null ? undefined : a.ba?.[x] // a === null ? undefined : a[x]a?.b() // a === null ? undefined : a.b()a?.() // a === null ? undefined : a()a?.b[3].c?.(x).d // a == null ? undefined : a.b[3].c == null ? undefined : a.b[3].c(x).d// optional deletiondelete a?.b // a === null ? true : delete a.b

不反对可选链的:

1、可选的构造函数: new a?.()2、可选的模块字符串: a?.`string`3、可选的属性赋值: a?.b = c4、可选的super: super?.(), super?.foo

globalThis

以前,在不同的JavaScript环境中获取全局对象须要不同的的语句,Web中能够通过window、self(Web workers)、frames取到全局对象,在Node.js中,应用global取得
当初能够对立应用globalThis来获取全局对象

Promise.allSettled()

返回一个在给定的promise都曾经fulfilled或rejected后的promise,并带有一个对象数组,每个对象示意对应的promise后果

const promise1 = Promise.resolve(3);const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));const promises = [promise1, promise2];Promise.allSettled(promises).  then((results) => results.forEach((result) => console.log(result.status)));// fulfilled// rejected

ES2021/ES12

String.prototype.replaceAll(searchValue, replaceValue)

已有的String.prototype.replace只能替换第一个匹配的,如果须要匹配所有,须要应用正则如果加全局合乎g
还能够应用split+join的办法达到替换所有
留神: replaceAll时,searchValue如果是正则然而是非全局时(即没有加g关键字),会引发异样,

Promise.any()

接管一个Promise可迭代对象,只有其中的一个promise胜利,就返回那个曾经胜利的promise,如果没有一个promise胜利,则返回一个失败的Promise
如果传入的参数是一个空的迭代对象,则会返回一个已失败状态的Promise
如果传入的参数不蕴含任何promise,则返回一个异步实现的promise
该办法会返回第一个胜利的 promise 。只有有一个 promise 胜利此办法就会终止,它不会期待其余的 promise 全副实现。

Promise.any([  fetch('https://v8.dev/').then(() => 'home'),  fetch('https://v8.dev/blog').then(() => 'blog'),  fetch('https://v8.dev/docs').then(() => 'docs')]).then((first) => {  // Any of the promises was fulfilled.  console.log(first);  // → 'home'}).catch((error) => {  // All of the promises were rejected.  console.log(error);});

Logical Assignment Operators(逻辑赋值操作符)

a ||= b // a || (a  = b)a ??= ba &&= b

数字分隔符(_)

在二进制、十六进制、BigInt中都能够应用

const x = 1000000000const y = 1000_000_000x === y // true