ES9新特性:

1异步迭代

在async/await,你可能在同步循环中调用异步函数,例如:



async function process(array){
     for(let i of array){
        await dosomething(i)      
    }  
}



这段代码不会正常运行,下面这段也不会正常运行:



async function process(array){
    array.forEach(async i => {
       await dosomething(i); 
    })
}



这段代码中,循环本身依旧保持同步,并在内部异步函数之前全部调用完毕。

ES2018引入异步迭代器(asynchronous iterators),这就像常规迭代器,除了next()方法返回一个promise。因此await可以和for...of循环一起使用,以串行的方式异步运作



async function process(array){
  for await (let i of array){    
    dosomething(i)    
  }      
}




2.Promise.finally()

一个promise调用链要么成功到达最后一个.then(),要么失败触发.catch()。在某些情况下,你想要在无论Promise运行成功还是失败,运行相同的代码,例如清除,删除对话,关闭数据连接等。

.funally()允许你指定最终的逻辑:



function dosomething(){
  dosomething1()
 .then(dosomething2)
 .then(dosomething3)
 .catch(err => {
    console.log(err);  
 })
 .finally(() => {});  
}



3.Rest/Spread

解构和扩展

4.正则表达式命名捕获组(groups)

js正则表达式可以返回一个匹配对象--一个包含匹配字符串的累数组,例如以YYYY-MM-DD的格式解析日期:



const reDate  = /([0-9]{4})-([0-9]{2})-([0.-9]{2})/,
    match = reDate.exec("2019-04-12"),
    year =  match[1],
    mouth =  match[2],
    day = match[3]



这样的代码很难读懂,并且改变正则表达式的结构有可能改变匹配对象的索引

ES2018允许命名捕获组使用?<name>,在打开捕获括号(后立即命名,示例:



const  reDate = /(?<year>[0-9]{4})-(?<mouth>[0-9]{2})-(?<day>[0-9]{2})/,
    match = reDate.exec("2019-04-12"),
   year = match.groups.year,
    mouth = match.groups.mouth,
    day  = match.groups.day



 

5正则表达式反向断言

目前js支持先行断言(lookahead),这意味着匹配会发生,但不会有任何捕获,并且断言没有包含在整个匹配字符字段中,例如:



const  
reLookahead  = /\D(?=\d+)/,
match = reLookahead.exec("$123.23")
console.log(match[0]) //$



ES2018引入以相同方式工作但是匹配前面的反向断言(lookbehind),这样我就可以忽略货币符号,单纯的捕获价格数字:



const
reLookbehind  = /(?<=\D)\d+/,
match = reLookbehind.exec("$123.23")
console.log(match[0])  //123



6正则表达式dotAll模式


正则表达式中点.匹配除回车以外的任何单字符,标记s改变这种方式,允许终止符的出现,例如:



/hello.world/.test("hello\nworld");
/hello.world/s.test("hello\nworld");



ES10新特性

1.行分隔符(U + 2028)和段分隔符(U + 2029)符号现在允许在字符串文字中,与JSON匹配

以前,这些符号在字符串文字中被视为行终止符,因此使用它们会导致SyntaxError异常。

2.更加友好的 JSON.stringify

如果输入 Unicode 格式但是超出范围的字符,在原先JSON.stringify返回格式错误的Unicode字符串。现在实现了一个改变JSON.stringify的第3阶段提案,因此它为其输出转义序列,使其成为有效Unicode(并以UTF-8表示)

3.新增了Array的 flat()方法和 flatMap()方法

flat()和 flatMap()本质上就是是归纳(reduce) 与 合并(concat)的操作。

Array.prototype.flat()

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。



var arr1 = [1,2,[3,4]];
arr1.flat();//[1,2,3,4];

var arr2 = [1,2,[3,4,[5,6]]];
arr2.flat(); //[1,2,3,4,[5,6]];

var arr3 = [1,2,[3,4,[5,6]]];
arr3.flat(2);//[1,2,3,4,5,6]  参数表示展开的深度



flat()



var arr4 = [1,2,,4,5]
arr4.flat();//[1,2,4,5]



Array.prototype.flatMap()

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。 这里我们拿map方法与flatMap方法做一个比较。



var arr1  = [1,2,3,5];
arr1.map(x => [x*2])
//(4) [Array(1), Array(1), Array(1), Array(1)]0: [2]1: [4]2: [6]3: 
arr1.flatMap(x => [x*2])
//(4) [2, 4, 6, 10]
arr1.flatMap(x => [[x*2]])
//(4) [Array(1), Array(1), Array(1), Array(1)]



4.新增了String的 trimStart()方法和 trimEnd()方法

新增的这两个方法很好理解,分别去除字符串首尾空白字符,这里就不用例子说声明了。  

5. Object.fromEntries()

Object.entries()方法的作用是返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。

而 Object.fromEntries() 则是 Object.entries() 的反转。

 通过 Object.fromEntries, 可以将 Map 转化为 Object:



const map1 = new Map([['foo','bar'],['baz',42]])
const obj122 = Object.fromEntries(map1)
obj1
//{foo: "bar", x: 41}



通过 Object.fromEntries, 可以将 Array 转化为 Object:



var obj32 = Object.fromEntries(arr1)
var obj32 = Object.fromEntries(arr21)
obj32
//{0: "a", 1: "b", 2: "c"}



6. String.prototype.matchAll

matchAll() 方法返回一个包含所有匹配正则表达式及分组捕获结果的迭代器。 在 matchAll 出现之前,通过在循环中调用regexp.exec来获取所有匹配项信息(regexp需使用/g标志

7. Function.prototype.toString()现在返回精确字符,包括空格和注释

头部和尾部的注释不显示

9.修改 catch 绑定

之前是try {}catch(e){}

现在是try {}catch{}

10.新的基本数据类型 BigInt

其中数据类型:String、Number、Boolean、Null、Undefined、Symbol、BigInt