es7,es8,es9新特性

2024-01-19 03:48
文章标签 特性 es7 es8 es9

本文主要是介绍es7,es8,es9新特性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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新特性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/621171

相关文章

ActiveMQ—消息特性(延迟和定时消息投递)

ActiveMQ消息特性:延迟和定时消息投递(Delay and Schedule Message Delivery) 转自:http://blog.csdn.net/kimmking/article/details/8443872 有时候我们不希望消息马上被broker投递出去,而是想要消息60秒以后发给消费者,或者我们想让消息没隔一定时间投递一次,一共投递指定的次数。。。 类似

PostgreSQL核心功能特性与使用领域及场景分析

PostgreSQL有什么优点? 开源和免费 PostgreSQL是一个开源的数据库管理系统,可以免费使用和修改。这降低了企业的成本,并为开发者提供了一个活跃的社区和丰富的资源。 高度兼容 PostgreSQL支持多种操作系统(如Linux、Windows、macOS等)和编程语言(如C、C++、Java、Python、Ruby等),并提供了多种接口(如JDBC、ODBC、ADO.NET等

详解Tomcat 7的七大新特性和新增功能(1)

http://developer.51cto.com/art/201009/228537.htm http://tomcat.apache.org/tomcat-7.0-doc/index.html  Apache发布首个Tomcat 7版本已经发布了有一段时间了,Tomcat 7引入了许多新功能,并对现有功能进行了增强。很多文章列出了Tomcat 7的新功能,但大多数并没有详细解释它们

如何掌握面向对象编程的四大特性、Lambda 表达式及 I/O 流:全面指南

这里写目录标题 OOP语言的四大特性lambda输入/输出流(I/O流) OOP语言的四大特性 面向对象编程(OOP)是一种编程范式,它通过使用“对象”来组织代码。OOP 的四大特性是封装、继承、多态和抽象。这些特性帮助程序员更好地管理复杂的代码,使程序更易于理解和维护。 类-》实体的抽象类型 实体(属性,行为) -》 ADT(abstract data type) 属性-》成

《C++标准库》读书笔记/第一天(C++新特性(1))

C++11新特性(1) 以auto完成类型自动推导 auto i=42; //以auto声明的变量,其类型会根据其初值被自动推倒出来,因此一定需要一个初始化操作; static auto a=0.19;//可以用额外限定符修饰 vector<string> v;  auto pos=v.begin();//如果类型很长或类型表达式复杂 auto很有用; auto l=[] (int

12C 新特性,MOVE DATAFILE 在线移动 包括system, 附带改名 NID ,cdb_data_files视图坏了

ALTER DATABASE MOVE DATAFILE  可以改名 可以move file,全部一个命令。 resue 可以重用,keep好像不生效!!! system照移动不误-------- SQL> select file_name, status, online_status from dba_data_files where tablespace_name='SYSTEM'

Cmake之3.0版本重要特性及用法实例(十三)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧

Java8特性:分组、提取字段、去重、过滤、差集、交集

总结下自己使用过的特性 将对象集合根据某个字段分组 //根据id分组Map<String, List<Bean>> newMap = successCf.stream().collect(Collectors.groupingBy(b -> b.getId().trim())); 获取对象集合里面的某个字段的集合 List<Bean> list = new ArrayList<>

【JVM】JVM栈帧中的动态链接 与 Java的面向对象特性--多态

栈帧 每一次方法调用都会有一个对应的栈帧被压入栈(虚拟机栈)中,每一个方法调用结束后,都会有一个栈帧被弹出。 每个栈帧中包括:局部变量表、操作数栈、动态链接、方法返回地址。 JavaGuide:Java内存区域详解(重点) 动态链接 动态链接:指向运行时常量池中该栈帧所属方法的引用。 多态 多态允许不同类的对象对同一消息做出响应,但表现出不同的行为(即方法的多样性)。 多态

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置