es7,es8,es9新特性


1. ES7新特性(ECMAScript 2016)

ES7在ES6的基础上主要添加了两项内容:

  • Array.prototype.includes()方法
  • 求幂运算符(**)

Array.prototype.includes()方法

includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

// ex
var array = [1, 2, 3];console.log(array.includes(2));
// expected output: truevar pets = ['cat', 'dog', 'bat'];console.log(pets.includes('cat'));
// expected output: trueconsole.log(pets.includes('at'));
// expected output: false

Array.prototype.includes()方法接收两个参数:

  • 要搜索的值

  • 搜索的开始索引

当第二个参数被传入时,该方法会从索引处开始往后搜索(默认索引值为0)。若搜索值在数组中存在则返回true,否则返回false。 且看下面示例:

// ex:
['a', 'b', 'c', 'd'].includes('b')         // true
['a', 'b', 'c', 'd'].includes('b', 1)      // true
['a', 'b', 'c', 'd'].includes('b', 2)      // false

和indexOf的区别,请看代码

// ex1:
var ary = [1];
if (ary.indexOf(1) !== -1) {console.log("数组存在1")
}
if (ary.includes(1)) {console.log("数组存在1")
}//ex2:
var ary1 = [NaN];
console.log(ary1.indexOf(NaN))//-1
console.log(ary1.includes(NaN))//true//ex3:
var ary1 = new Array(3);
console.log(ary1.indexOf(undefined));//-1
console.log(ary1.includes(undefined))//true

求幂运算符(**)

加/减法我们通常都是用其中缀形式,直观易懂。在ECMAScript2016中,我们可以使用**来替代Math.pow。

4 ** 3           // 64
// 等价于
Math.pow(4,3)//  值得一提的是,作为中缀运算符,**还支持以下操作
let n = 4;
n **= 3;
// 64

2.ES8新特性(ECMAScript 2017)

主要新功能:

  • 异步函数 Async Functions

次要新功能:

  • Object.values / Object.entries
  • String padding
  • Object.getOwnPropertyDescriptors()
  • 函数参数列表和调用中的尾逗号

Async Functions

Async Functions也就是我们常说的Async/Await,相信大家对于这个概念都已经不陌生了。Async/Await是一种用于处理JS异步操作的语法糖,可以帮助我们摆脱回调地狱,编写更加优雅的代码。

通俗的理解,async关键字的作用是告诉编译器对于标定的函数要区别对待。当编译器遇到标定的函数中的await关键字时,要暂时停止运行,带到await标定的函数处理完毕后,再进行相应操作。如果该函数fulfiled了,则返回值是fulfillment value,否则得到的就是reject value。

几种常见的用法,下面通过拿普通的promise写法来对比,就很好理解了:

// ex:
async function asyncFunc() {const result = await otherAsyncFunc();console.log(result);
}// Equivalent to:
function asyncFunc() {return otherAsyncFunc().then(result => {console.log(result);});
}//按顺序处理多个异步函数的时候优势更为明显:
async function asyncFunc() {const result1 = await otherAsyncFunc1();console.log(result1);const result2 = await otherAsyncFunc2();console.log(result2);
}// Equivalent to:
function asyncFunc() {return otherAsyncFunc1().then(result1 => {console.log(result1);return otherAsyncFunc2();}).then(result2 => {console.log(result2);});
}
//  并行处理多个异步函数:
async function asyncFunc() {const [result1, result2] = await Promise.all([otherAsyncFunc1(),otherAsyncFunc2(),]);console.log(result1, result2);
}// Equivalent to:
function asyncFunc() {return Promise.all([otherAsyncFunc1(),otherAsyncFunc2(),]).then([result1, result2] => {console.log(result1, result2);});
}// 处理错误:
async function asyncFunc() {try {await otherAsyncFunc();} catch (err) {console.error(err);}
}// Equivalent to:
function asyncFunc() {return otherAsyncFunc().catch(err => {console.error(err);});
}

Object.values and Object.entries

Object.values() 方法返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for…in循环的顺序相同 ( 区别在于for-in循环枚举原型链中的属性 )。

obj参数是需要待操作的对象。可以是一个对象,或者一个数组(是一个带有数字下标的对象,[10,20,30] -> {0: 10,1: 20,2: 30})。

// ex:
const obj = { x: 'xxx', y: 1 };
Object.values(obj); // ['xxx', 1]const obj = ['e', 's', '8']; // 相当于 { 0: 'e', 1: 's', 2: '8' };
Object.values(obj); // ['e', 's', '8']// 当我们使用数字键值时,返回的是数字排序
// 根据键值排序
const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.values(obj); // ['yyy', 'zzz', 'xxx']Object.values('es8'); // ['e', 's', '8']

Object.entries 方法返回一个给定对象自身可遍历属性 [key, value] 的数组, 排序规则和 Object.values 一样。这个方法的声明比较琐碎:

// ex:
const obj = { x: 'xxx', y: 1 };
Object.entries(obj); // [['x', 'xxx'], ['y', 1]]const obj = ['e', 's', '8'];
Object.entries(obj); // [['0', 'e'], ['1', 's'], ['2', '8']]const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]Object.entries('es8'); // [['0', 'e'], ['1', 's'], ['2', '8']]

String padding

为 String 对象增加了 2 个函数:padStart 和 padEnd。

像它们名字那样,这几个函数的主要目的就是填补字符串的首部和尾部,为了使得到的结果字符串的长度能达到给定的长度。你可以通过特定的字符,或者字符串,或者默认的空格填充它。下面是函数的声明:

str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])

这些函数的第一个参数是 targetLength(目标长度),这个是结果字符串的长度。第二个参数是可选的 padString(填充字符),一个用于填充到源字符串的字符串。默认值是空格。

'es8'.padStart(2);          // 'es8'
'es8'.padStart(5);          // '  es8'
'es8'.padStart(6, 'woof');  // 'wooes8'
'es8'.padStart(14, 'wow');  // 'wowwowwowwoes8'
'es8'.padStart(7, '0');     // '0000es8''es8'.padEnd(2);            // 'es8'
'es8'.padEnd(5);            // 'es8  '
'es8'.padEnd(6, 'woof');    // 'es8woo'
'es8'.padEnd(14, 'wow');    // 'es8wowwowwowwo'
'es8'.padEnd(7, '6');       // 'es86666'

Object.getOwnPropertyDescriptors

getOwnPropertyDescriptors 方法返回指定对象所有自身属性的描述对象。属性描述对象是直接在对象上定义的,而不是继承于对象的原型。ES2017加入这个函数的主要动机在于方便将一个对象深度拷贝给另一个对象,同时可以将getter/setter拷贝。声明如下:

Object.getOwnPropertyDescriptors(obj)

obj 是待操作对象。返回的描述对象键值有:configurable, enumerable, writable, get, set and value。

const obj = { get es7() { return 777; },get es8() { return 888; }
};
Object.getOwnPropertyDescriptors(obj);
// {
//   es7: {
//     configurable: true,
//     enumerable: true,
//     get: function es7(){}, //the getter function
//     set: undefined
//   },
//   es8: {
//     configurable: true,
//     enumerable: true,
//     get: function es8(){}, //the getter function
//     set: undefined
//   }
// }

结尾逗号

结尾逗号用代码展示非常明了:

// 参数定义时
function foo(param1,param2,
) {}// 函数调用时
foo('abc','def',
);// 对象中
let obj = {first: 'Jane',last: 'Doe',
};// 数组中
let arr = ['red','green','blue',
];

这个改动有什么好处呢?

  • 首先,重新排列项目更简单,因为如果最后一项更改其位置,则不必添加和删除逗号。
  • 其次,它可以帮助版本控制系统跟踪实际发生的变化。例如,从:
['foo'
]

修改为

['foo','bar'
]

导致线条’foo’和线条’bar’被标记为已更改,即使唯一真正的变化是后一条线被添加。

3,ES9新特性(ECMAScript 2018)

主要新功能:

  • 异步迭代
  • Rest/Spread 属性

新的正则表达式功能:

  • RegExp named capture groups
  • RegExp Unicode Property Escapes(Mathias Bynens)
  • RegExp Lookbehind Assertions

其他新功能:

  • Promise.prototype.finally()
  • 模板字符串修改

异步迭代

首先来回顾一下同步迭代器:

ES6引入了同步迭代器,其工作原理如下:

  • Iterable:一个对象,表示可以通过Symbol.iterator方法进行迭代。
  • Iterator:通过调用iterable [Symbol.iterator] ()返回的对象。它将每个迭代元素包装在一个对象中,并通过其next()方法一次返回一个。
  • IteratorResult:返回的对象next()。属性value包含一个迭代的元素,属性done是true 后最后一个元素。

示例:

const iterable = ['a', 'b'];
const iterator = iterable[Symbol.iterator]();
iterator.next()
// { value: 'a', done: false }
iterator.next()
// { value: 'b', done: false }
iterator.next()
// { value: undefined, done: true }

异步迭代器

先前的迭代方式是同步的,并不适用于异步数据源。例如,在以下代码中,readLinesFromFile()无法通过同步迭代传递其异步数据:


function readLinesFromFile (){setTimeout(() => {return "123456"},1000)
}
for (const line of readLinesFromFile()) {console.log(line);
}
function *createNumberIterator(){yield 1;yield 2;yield 3;}const iterator = createNumberIterator();const p2 = iterator.next(); // Object {value: 2, done: false}const p3 = iterator.next(); // Object {value: 3, done: false}const p4 = iterator.next(); // Object {value: undefined, done: true}const p1 = iterator.next(); // Object {value: 1, done: false}log(p1, p2, p3, p4)

异步迭代器和常规迭代器的工作方式非常相似,但是异步迭代器涉及promise:

async function example() {// 普通迭代器:const iterator = createNumberIterator();iterator.next(); // Object {value: 1, done: false}iterator.next(); // Object {value: 2, done: false}iterator.next(); // Object {value: 3, done: false}iterator.next(); // Object {value: undefined, done: true}// 异步迭代器:const asyncIterator = createAsyncNumberIterator();const p = asyncIterator.next(); // Promiseawait p;// Object {value: 1, done: false}await asyncIterator.next(); // Object {value: 2, done: false}await asyncIterator.next(); // Object {value: 3, done: false}await asyncIterator.next(); // Object {value: undefined, done: true}
}

异步迭代器对象的next()方法返回了一个Promise,解析后的值跟普通的迭代器类似。
用法:iterator.next().then(({ value, done })=> {//{value: ‘some val’, done: false}}

const promises = [new Promise(resolve => resolve(1)),new Promise(resolve => resolve(2)),new Promise(resolve => resolve(3)),
];async function test() {for await (const p of promises) {console.log(p);}
}
test(); //1 ,2 3

Rest/Spread 属性

这个就是我们通常所说的rest参数和扩展运算符,这项特性在ES6中已经引入,但是ES6中的作用对象仅限于数组

restParam(1, 2, 3, 4, 5);function restParam(p1, p2, ...p3) {// p1 = 1// p2 = 2// p3 = [3, 4, 5]
}const values = [99, 100, -1, 48, 16];
console.log( Math.max(...values) ); // 100

在ES9中,为对象提供了像数组一样的rest参数和扩展运算符:

const obj = {a: 1,b: 2,c: 3
}
const { a, ...param } = obj;console.log(a)     //1console.log(param) //{b: 2, c: 3}function foo({a, ...param}) {console.log(a);    //1console.log(param) //{b: 2, c: 3}
}

正则表达式命名捕获组

编号的捕获组

//正则表达式命名捕获组
const RE_DATE = /([0-9]{4})-([0-9]{2})-([0-9]{2})/;const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31

通过数字引用捕获组有几个缺点:

  • 找到捕获组的数量是一件麻烦事:必须使用括号。
  • 如果要了解组的用途,则需要查看正则表达式。
  • 如果更改捕获组的顺序,则还必须更改匹配代码。

命名的捕获组

ES9中可以通过名称来识别捕获组:(?<year>[0-9]{4})

在这里,我们用名称标记了前一个捕获组year。该名称必须是合法的JavaScript标识符(认为变量名称或属性名称)。匹配后,您可以通过访问捕获的字符串matchObj.groups.year来访问。

让我们重写前面的代码:

const RE_DATE = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31// 使用解构语法更为简便
const {groups: {day, year}} = RE_DATE.exec('1999-12-31');
console.log(year); // 1999
console.log(day); // 31

可以发现,命名捕获组有以下优点:

  • 找到捕获组的“ID”更容易。
  • 匹配代码变为自描述性的,因为捕获组的ID描述了正在捕获的内容。
  • 如果更改捕获组的顺序,则无需更改匹配代码。
  • 捕获组的名称也使正则表达式更容易理解,因为您可以直接看到每个组的用途。

正则表达式 Unicode 转义

该特性允许您使用\p{}通过提及大括号内的Unicode字符属性来匹配字符,在正则表达式中使用标记 u (unicode) 设置。

/^\p{White_Space}+$/u.test('\t \n\r')
// true
/^\p{Script=Greek}+$/u.test('μετά')
// true

新方法匹配中文字符

由于在Unicode里面,中文字符对应的Unicode Script是Han,于是我们就可以用这个reg来匹配中文:

/\p{Script=Han}/u
这样我们就可以不用记忆繁琐又不好记的/[\u4e00-\u9fa5]/了,况且这个表达式已经有些年头了,说实话,后来又新增的属性为Han的字符并不在这个范围内,因此这个有年头reg并不一定好使。

我随便从网上找了一个Unicode8.0添加的中文字符“?”,我测了一下两种reg的兼容性:

oldReg=/[\u4e00-\u9fa5]/
newReg=/\p{Script=Han}/uoldReg.test('abc')
// false
newReg.test('abc')
// falseoldReg.test('地平线')
// true
newReg.test('地平线')
// trueoldReg.test('?')
// false
newReg.test('?')
// true

正则表达式反向断言

先来看下正则表达式先行断言是什么:

如获取货币的符号

const noReLookahead = /\D(\d+)/,reLookahead = /\D(?=\d+)/,match1 = noReLookahead.exec('$123.45'),match2 = reLookahead.exec('$123.45');
console.log(match1[0]); // $123
console.log(match2[0]); // $

在ES9中可以允许反向断言:

const reLookahead = /(?<=\D)[\d\.]+/;match = reLookahead.exec('$123.45');
console.log(match[0]); // 123.45

使用?<=进行反向断言,可以使用反向断言获取货币的价格,而忽略货币符号。

Promise.prototype.finally()

promise.then(result => {···}).catch(error => {···}).finally(() => {···});

finally的回调总会被执行。注意.finally()执行之后便在.then 或者.catch的话是不会执行的

模板字符串修改

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

要取消转义序列的语法限制,可在模板字符串之前使用标记函数String.raw:

`\u{54}`
// "T"
String.raw`\u{54}`
// "\u{54}"

参考

  • 原文档

es7,es8,es9新特性相关推荐

  1. ES7和ES8常见新特性

    文章目录 1.ES7新特性 1.1 Array Includes 1.2 指数运算符 2.ES8新特性 2.1 Object values 2.2 Object entries 2.3 String/ ...

  2. 【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)

    一.介绍 现在的网络上已经有各样关于 ECMAScript 规范介绍和分析的文章,而我自己重新学习一遍这些规范,整理出这么一份笔记,比较精简,主要内容涵盖ES6.ES7.ES8.ES9,后续会增加面试 ...

  3. ES9新特性、ES10新特性

    ES9新特性 一.rest参数与spread扩展运算符 rest参数与spread扩展运算符在es6中已经引入,不过es6中只针对于数组,在es9中为对象提供了像数组一样的rest参数和扩展运算符 1 ...

  4. ES7 ES8 ES9 ES10 新特性总结思考

    学习在于总结,发现并没有对于新出的一些语言特性进行总结,正好最近有时间,可以把这些进行总结以及运用,也许在项目中已经使用. ES7 Array includes方法 求幂运算符 ES8 Async F ...

  5. ES6/ES7/ES8/ES9/ES10常用特性和新特性最全总结

    ES6 ES6在ES5的基础上新增了一系列特性,这里仅列出常用特性 变量的改变,添加了块级作用域的概念 let声明变量(块级作用域),let是更完美的var,它声明的全局变量不是全局属性widow的变 ...

  6. ES6, ES7, ES8, ES9 以及 ES10 新特征

    目录 1.  ES6 新特征 (2015) 1.1 module 1.1.1 export 1.1.2 import 1.2 Arrow function (箭头函数) 1.2.1 箭头函数结构 1. ...

  7. 深入理解ES8的新特性SharedArrayBuffer

    简介 ES8引入了SharedArrayBuffer和Atomics,通过共享内存来提升workers之间或者worker和主线程之间的消息传递速度. 本文将会详细的讲解SharedArrayBuff ...

  8. ES9新特性_ES9正则扩展-dotAll模式---JavaScript_ECMAScript_ES6-ES11新特性工作笔记056

    然后我们再来看一下这个,es9中对,正则表达式的扩展 dotAll的模式. 首先我们有这样的文本,一个<ul>,这样 然后我们要从里面获取a标签里面的内容,比如和上映日期. 可以看到上面这 ...

  9. ES9新特性_ES9正则扩展-反向断言---JavaScript_ECMAScript_ES6-ES11新特性工作笔记055

    然后我们再来看,正则表达式中es9中的,这个 反向断言. 可以看到,我们这里用了个?=啦,这个是什么意思,就是说我们根据,?=啦 就是匹配啦前面是不是数字. 可以看到结果右边.这叫做正向断言,就是通过 ...

最新文章

  1. linux块设备的IO调度算法和回写机制
  2. Mysql-linux下密码修改,忘记密码修改,超级管理用户修改
  3. Contest Hunter CH6201 走廊泼水节 最小生成树 Kruskal
  4. 如何去掉字符串最后的逗号?(亲测)
  5. vpn mysql_MYSQL数据库
  6. ta-lib依赖安装问题
  7. TCP协议无边界的问题
  8. 实用的工具 —— 百度云、everything(全局搜索)、Everest(硬件检测)、TechPowerUp GPU-Z
  9. Atitit spring 3.0 3.1 3.2 4.0 4.3 5.0 新特性
  10. 第三方登录/分享最佳实践
  11. android 9图工具位子,Android自定义9宫格图片视图
  12. storm DRPC问题
  13. SQL server 2012 下载,安装,磁力链接,下载地址 2020.11.28
  14. scrollToBottom
  15. php采集彩票开奖数据
  16. 在CygWin中设置proxy
  17. [C#]获取窗口客户区域、标题栏高度、菜单栏高度、边框宽度正确方法
  18. html 的描点链接
  19. Samba实现Linux与windows文件共享
  20. dg建立linux分区,Linux 下 Oracle 11g DG搭建

热门文章

  1. 【python学习小案例】提高兴趣之BMI计算器
  2. 小米5S TWRP刷面具、EdXposed
  3. 如何处理u盘一插进电脑就自动打开里面的所有文件夹
  4. uefi装完系统后无法引导_Win10用UEFI模式安装无法引导启动的原因分析及解决方法...
  5. 蓍草占卜Python法
  6. 综合布线系统工程中计算机插座的标识符号是,TD是综合布线系统工程中计算机插座的标识符号。...
  7. 用数字计算机公式表白,用最浪漫的数学表白,爱情数学表白公式
  8. 【Practical】积分第一中值定理
  9. 关于微信小程序与Java后台交互数据中中文乱码问题的讨论
  10. JIAR安装报错IRA Startup Failed