ES全称ECMAScript,下面将会列出ES2018(ES9)中已经进入stage-4的新特性。

新特性列表

ES2018新特性有:

1.对象的扩展运算符

2.正则表达式的改进

3.异步迭代器和异步生成器

4.Promise的finally回调

一、对象的拓展运算符

拓展运算符,也叫Rest/Spread,在ES6时提出了数组的扩展运算符,仅用于数组,而在ES9中则新增了对象的拓展运算符。扩展运算符用...表示。

用法:

ES6:

example1:

const arr = [1,2,3,4,5];
const [a,b,...c] = arr;

console.log(a,b); //1 2
console.log(c); //[3,4,5]

example2:

const nums = [23,12,3,12,3];
const result = Math.max(...nums);

console.log(result); //23

ES9:

example3:

const obj = { a : 1 , b : 2 , c : 3 , d : 4};
const {a , b , ...z} = obj;

console.log(a,b); //1 2
console.log(z); // { c : 3 , d : 4}

example4:

const obj1 = { a : 1 , b : 2};
const obj2 = {c : 3 , d : 4};

const obj3 = {...obj1 , ...obj2}; //合并对象

console.log(obj3); //{ a : 1 , b : 2 , c : 3 , d : 4};

注意:

1.解构赋值必须是最后一个参数,否则会报错。

2.解构赋值的后的对象创建的是新的引用。

const obj1 = { a : 1}; 
const {...obj2} = obj1;

console.log(obj2); //{ a : 1}

obj1.a = 2;

console.log(obj1); // { a : 2}
console.log(obj2); //{ a : 1}


二、正则表达式的改进

在ES9中,对于正则表达式的改进主要有四个方面:

1.位置运算符
2.Unicode转义
3.命名捕获组
4.修饰符s

用法:

1.位置修饰符

位置修饰符主要有四个:

q?=p :捕获q的后面是有p的字符串

const reg = /hello(?= world)/;

reg.test('a hello world sentences'); //true
reg.test('a hello kugou'); //false


q?!p :捕获q的后面不为p的字符串

const reg = /hello(?= world)/;

reg.test('a hello world sentences'); //false
reg.test('a hello kugou'); //true


(?<=q)p :捕获p前面有q的字符串

const reg = /(?<=hello) world/;

reg.test('a hello world sentences'); //true
reg.test('a haha kugou'); //false


(?<!q)p :捕获p前面没有q的字符串

const reg = /(?<!hello) world/;

reg.test('a hello world sentences'); //false
reg.test('a haha world'); //true


2.Unicode转义

Unicode转义可以通过\p{...}捕获,\P{...}捕获的是不符合转义的字符串。大括号内可以传入不同类型的unicode字符关键字,以下是不同unicode字符关键字的示例:

ASCII :捕获ASCII 字符集的字符串

const reg = /^\p{ASCII}+$/u;

reg.test('abc'); //true
reg.test('abc🙃'); //false

ASCII_Hex_Digit : 捕获16进制数字字符串

const reg = /^\p{ASCII_Hex_Digit}+$/u;

reg.test('012EF'); //true
reg.test('G'); //false

Uppercase/Lowercase : 捕获大或小写的字符串

/\p{Uppercase}/u.test('A'); //true
/\p{Lowercase}/u.test('a'); //true

White_Space :捕获空格

/\p{White_Space}/u.test(' ') //true

Emoji : 捕获emoji表情

/\p{Emoji}/u.test('🙃');    //true

这里列出了部分的unicode关键字,还有其他更多可以查看https://github.com/tc39/proposal-regexp-unicode-property-escapes

3.命名捕获组

捕获结果中新增了groups对象,可以将捕获一些字段放入捕获结果的groups中。格式为(?<name>Regexp),其中name为groups中的key值,可以通过该key值拿到捕获的结果,Regexp为要捕获的正则表达式。

const reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const result = reg.exec('2015-01-02');
console.log(reuslt.groups); //{year: "2015", month: "01", day: "02"}
4.修饰符s

增加了新的修饰符s,可以让.匹配任意的字符,包括换行符。又叫dot all。

/hello.world/.test('hello\nworld');	//false
/hello.world/s.test('hello\nworld'); //true

三、异步迭代器和异步生成器

迭代器和生成器

迭代器(Iterator)和生成器(Generator)于ES6中提出。

Iterator主要用于遍历不同的数据结构,遍历的数据结构要具有Symbol.iterator属性。Iterator中包含next方法,调用next方法可以返回两个值为valuedonevalue为返回的值,done为标识遍历是否结束,当为false时,遍历未结束,当为true时,遍历结束。ES6提供了for...of来遍历Iterator数据。

数组是默认具有Symbol.iterator属性的,以数组为例:

const arr = ['a','b','c','d','e'];

console.log(typeof arr[Symbol.iterator]); //function

for(let item of arr){
console.log(item);
}
//a
//b
//c
//d
//e

Generator函数是ES6提供的一种异步解决方案。执行Generator函数会返回一个遍历器对象,返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。Generator函数有两个特征,一是function关键字与函数名之间有一个*号,二是函数体内部使用yield表达式,定义不同的内部状态。

function* Test(){
console.log('start');
yield 1;
yield 2;
console.log('end');
return 3;
}

const test = Test();

console.log(typeof test[Symbol.iterator]); //function

test.next(); //start {value: 1, done: false}
test.next(); //{value: 2, done: false}
test.next(); //end {value: 3, done: true}

异步迭代器和异步生成器

异步迭代器与同步迭代器的区别在于,同步迭代器的next方法返回的是包含valuedone的对象,异步迭代器的next方法返回的是promise对象,且promise对象回调中参数包含valuedone对象。异步迭代器中包含的Symbol.asyncIterator属性。

asyncIterator.next().then(({value , done}) => {
console.log(value , done);
})

异步生成器与普通生成器在于,异步生成器的定义加入了async,且内部可以使用await,返回的是一个具有Symbol.asyncIterator方法的对象。因此可以用异步生成器创建异步迭代器。

async function* Test(){
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}

const test = Test();

console.log(test[Symbol.asyncIterator]); //function

for...of只能用来遍历同步迭代器,因此ES9提供了for...await...of来遍历异步迭代器。

for await (const item of test){
console.log(item);
}
//1
//2
//3


四、Promise的finally回调

在ES9中,新增了Promise的finally回调函数,无论Promise返回结果是成功执行then()还是失败执行catch(),都会执行finally回调函数。

function test(num){
return new Promise((resolve , reject) => {
if(num == 1){
resolve()
}else{
reject();
}
})
}

test(1).then(() => {
console.log('success')
}).finally(() => {
console.log('finally')
})
//success
//finally

test(2).catch(() => {
console.log('error')
}).finally(() => {
console.log('finally')
})
//error
//finally


参考文档

1.THE ES2018 GUIDE

2.ES9中的异步迭代器(Async iterator)和异步生成器(Async generator)